]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fa02c335663adc98c11a62a86d23121fcbc8f1c6
[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 USESHADOWMAPPCF 1\n", " shadowmappcf"}, // TODO make this a static parm
649         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, // TODO make this a static parm
650         {"#define USESHADOWSAMPLER\n", " shadowsampler"}, // TODO make this a static parm
651         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
652         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
653         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
654         {"#define USEALPHAKILL\n", " alphakill"},
655         {"#define USEREFLECTCUBE\n", " reflectcube"},
656         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
657         {"#define USEBOUNCEGRID\n", " bouncegrid"},
658         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
659         {"#define USETRIPPY\n", " trippy"},
660         {"#define USEDEPTHRGB\n", " depthrgb"},
661 };
662
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 struct r_glsl_permutation_s;
709 typedef struct r_glsl_permutation_s
710 {
711         /// hash lookup data
712         struct r_glsl_permutation_s *hashnext;
713         unsigned int mode;
714         unsigned int permutation;
715
716         /// indicates if we have tried compiling this permutation already
717         qboolean compiled;
718         /// 0 if compilation failed
719         int program;
720         // texture units assigned to each detected uniform
721         int tex_Texture_First;
722         int tex_Texture_Second;
723         int tex_Texture_GammaRamps;
724         int tex_Texture_Normal;
725         int tex_Texture_Color;
726         int tex_Texture_Gloss;
727         int tex_Texture_Glow;
728         int tex_Texture_SecondaryNormal;
729         int tex_Texture_SecondaryColor;
730         int tex_Texture_SecondaryGloss;
731         int tex_Texture_SecondaryGlow;
732         int tex_Texture_Pants;
733         int tex_Texture_Shirt;
734         int tex_Texture_FogHeightTexture;
735         int tex_Texture_FogMask;
736         int tex_Texture_Lightmap;
737         int tex_Texture_Deluxemap;
738         int tex_Texture_Attenuation;
739         int tex_Texture_Cube;
740         int tex_Texture_Refraction;
741         int tex_Texture_Reflection;
742         int tex_Texture_ShadowMap2D;
743         int tex_Texture_CubeProjection;
744         int tex_Texture_ScreenNormalMap;
745         int tex_Texture_ScreenDiffuse;
746         int tex_Texture_ScreenSpecular;
747         int tex_Texture_ReflectMask;
748         int tex_Texture_ReflectCube;
749         int tex_Texture_BounceGrid;
750         /// locations of detected uniforms in program object, or -1 if not found
751         int loc_Texture_First;
752         int loc_Texture_Second;
753         int loc_Texture_GammaRamps;
754         int loc_Texture_Normal;
755         int loc_Texture_Color;
756         int loc_Texture_Gloss;
757         int loc_Texture_Glow;
758         int loc_Texture_SecondaryNormal;
759         int loc_Texture_SecondaryColor;
760         int loc_Texture_SecondaryGloss;
761         int loc_Texture_SecondaryGlow;
762         int loc_Texture_Pants;
763         int loc_Texture_Shirt;
764         int loc_Texture_FogHeightTexture;
765         int loc_Texture_FogMask;
766         int loc_Texture_Lightmap;
767         int loc_Texture_Deluxemap;
768         int loc_Texture_Attenuation;
769         int loc_Texture_Cube;
770         int loc_Texture_Refraction;
771         int loc_Texture_Reflection;
772         int loc_Texture_ShadowMap2D;
773         int loc_Texture_CubeProjection;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_OffsetMapping_LodDistance;
806         int loc_OffsetMapping_Bias;
807         int loc_PixelSize;
808         int loc_ReflectColor;
809         int loc_ReflectFactor;
810         int loc_ReflectOffset;
811         int loc_RefractColor;
812         int loc_Saturation;
813         int loc_ScreenCenterRefractReflect;
814         int loc_ScreenScaleRefractReflect;
815         int loc_ScreenToDepth;
816         int loc_ShadowMap_Parameters;
817         int loc_ShadowMap_TextureScale;
818         int loc_SpecularPower;
819         int loc_UserVec1;
820         int loc_UserVec2;
821         int loc_UserVec3;
822         int loc_UserVec4;
823         int loc_ViewTintColor;
824         int loc_ViewToLight;
825         int loc_ModelToLight;
826         int loc_TexMatrix;
827         int loc_BackgroundTexMatrix;
828         int loc_ModelViewProjectionMatrix;
829         int loc_ModelViewMatrix;
830         int loc_PixelToScreenTexCoord;
831         int loc_ModelToReflectCube;
832         int loc_ShadowMapMatrix;
833         int loc_BloomColorSubtract;
834         int loc_NormalmapScrollBlend;
835         int loc_BounceGridMatrix;
836         int loc_BounceGridIntensity;
837 }
838 r_glsl_permutation_t;
839
840 #define SHADERPERMUTATION_HASHSIZE 256
841
842
843 // non-degradable "lightweight" shader parameters to keep the permutations simpler
844 // these can NOT degrade! only use for simple stuff
845 enum
846 {
847         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
848         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
849         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
853         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
854         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
855 };
856 #define SHADERSTATICPARMS_COUNT 8
857
858 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
859 static int shaderstaticparms_count = 0;
860
861 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
862 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
863 static qboolean R_CompileShader_CheckStaticParms(void)
864 {
865         static int r_compileshader_staticparms_save[1];
866         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
867         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
868
869         // detect all
870         if (r_glsl_saturation_redcompensate.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
872         if (r_glsl_vertextextureblend_usebothalphas.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
874         if (r_shadow_glossexact.integer)
875                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
876         if (r_glsl_postprocess.integer)
877         {
878                 if (r_glsl_postprocess_uservec1_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
880                 if (r_glsl_postprocess_uservec2_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
882                 if (r_glsl_postprocess_uservec3_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
884                 if (r_glsl_postprocess_uservec4_enable.integer)
885                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
886         }
887         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
889         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
890 }
891
892 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
893         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
895         else \
896                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
897 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
898 {
899         shaderstaticparms_count = 0;
900
901         // emit all
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
910 }
911
912 /// information about each possible shader permutation
913 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
914 /// currently selected permutation
915 r_glsl_permutation_t *r_glsl_permutation;
916 /// storage for permutations linked in the hash table
917 memexpandablearray_t r_glsl_permutationarray;
918
919 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
920 {
921         //unsigned int hashdepth = 0;
922         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
923         r_glsl_permutation_t *p;
924         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
925         {
926                 if (p->mode == mode && p->permutation == permutation)
927                 {
928                         //if (hashdepth > 10)
929                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
930                         return p;
931                 }
932                 //hashdepth++;
933         }
934         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
935         p->mode = mode;
936         p->permutation = permutation;
937         p->hashnext = r_glsl_permutationhash[mode][hashindex];
938         r_glsl_permutationhash[mode][hashindex] = p;
939         //if (hashdepth > 10)
940         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
941         return p;
942 }
943
944 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
945 {
946         char *shaderstring;
947         if (!filename || !filename[0])
948                 return NULL;
949         if (!strcmp(filename, "glsl/default.glsl"))
950         {
951                 if (!glslshaderstring)
952                 {
953                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
954                         if (glslshaderstring)
955                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
956                         else
957                                 glslshaderstring = (char *)builtinshaderstring;
958                 }
959                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
960                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
961                 return shaderstring;
962         }
963         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964         if (shaderstring)
965         {
966                 if (printfromdisknotice)
967                         Con_DPrintf("from disk %s... ", filename);
968                 return shaderstring;
969         }
970         return shaderstring;
971 }
972
973 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
974 {
975         int i;
976         int sampler;
977         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
978         char *vertexstring, *geometrystring, *fragmentstring;
979         char permutationname[256];
980         int vertstrings_count = 0;
981         int geomstrings_count = 0;
982         int fragstrings_count = 0;
983         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
984         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
985         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
986
987         if (p->compiled)
988                 return;
989         p->compiled = true;
990         p->program = 0;
991
992         permutationname[0] = 0;
993         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
994         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
995         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
996
997         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
998
999         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1000         if(vid.support.gl20shaders130)
1001         {
1002                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1003                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1004                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1005                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1006                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1007                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1008         }
1009
1010         // the first pretext is which type of shader to compile as
1011         // (later these will all be bound together as a program object)
1012         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1013         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1014         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1015
1016         // the second pretext is the mode (for example a light source)
1017         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1018         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1019         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1020         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1021
1022         // now add all the permutation pretexts
1023         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1024         {
1025                 if (permutation & (1<<i))
1026                 {
1027                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1029                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1030                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1031                 }
1032                 else
1033                 {
1034                         // keep line numbers correct
1035                         vertstrings_list[vertstrings_count++] = "\n";
1036                         geomstrings_list[geomstrings_count++] = "\n";
1037                         fragstrings_list[fragstrings_count++] = "\n";
1038                 }
1039         }
1040
1041         // add static parms
1042         R_CompileShader_AddStaticParms(mode, permutation);
1043         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         vertstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         geomstrings_count += shaderstaticparms_count;
1047         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1048         fragstrings_count += shaderstaticparms_count;
1049
1050         // now append the shader text itself
1051         vertstrings_list[vertstrings_count++] = vertexstring;
1052         geomstrings_list[geomstrings_count++] = geometrystring;
1053         fragstrings_list[fragstrings_count++] = fragmentstring;
1054
1055         // if any sources were NULL, clear the respective list
1056         if (!vertexstring)
1057                 vertstrings_count = 0;
1058         if (!geometrystring)
1059                 geomstrings_count = 0;
1060         if (!fragmentstring)
1061                 fragstrings_count = 0;
1062
1063         // compile the shader program
1064         if (vertstrings_count + geomstrings_count + fragstrings_count)
1065                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1066         if (p->program)
1067         {
1068                 CHECKGLERROR
1069                 qglUseProgram(p->program);CHECKGLERROR
1070                 // look up all the uniform variable names we care about, so we don't
1071                 // have to look them up every time we set them
1072
1073                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1074                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1075                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1076                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1077                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1078                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1079                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1080                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1081                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1082                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1083                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1084                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1085                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1086                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1087                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1088                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1089                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1090                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1091                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1092                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1093                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1094                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1095                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1096                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1097                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1098                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1099                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1100                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1101                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1102                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1103                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1104                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1105                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1106                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1107                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1108                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1109                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1110                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1111                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1112                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1113                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1114                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1115                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1116                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1117                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1118                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1119                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1120                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1121                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1122                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1123                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1124                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1125                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1126                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1127                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1128                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1129                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1130                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1131                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1132                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1133                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1134                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1135                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1136                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1137                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1138                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1139                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1140                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1141                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1142                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1143                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1144                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1145                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1146                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1147                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1148                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1149                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1150                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1151                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1152                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1153                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1154                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1155                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1156                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1157                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1158                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1159                 // initialize the samplers to refer to the texture units we use
1160                 p->tex_Texture_First = -1;
1161                 p->tex_Texture_Second = -1;
1162                 p->tex_Texture_GammaRamps = -1;
1163                 p->tex_Texture_Normal = -1;
1164                 p->tex_Texture_Color = -1;
1165                 p->tex_Texture_Gloss = -1;
1166                 p->tex_Texture_Glow = -1;
1167                 p->tex_Texture_SecondaryNormal = -1;
1168                 p->tex_Texture_SecondaryColor = -1;
1169                 p->tex_Texture_SecondaryGloss = -1;
1170                 p->tex_Texture_SecondaryGlow = -1;
1171                 p->tex_Texture_Pants = -1;
1172                 p->tex_Texture_Shirt = -1;
1173                 p->tex_Texture_FogHeightTexture = -1;
1174                 p->tex_Texture_FogMask = -1;
1175                 p->tex_Texture_Lightmap = -1;
1176                 p->tex_Texture_Deluxemap = -1;
1177                 p->tex_Texture_Attenuation = -1;
1178                 p->tex_Texture_Cube = -1;
1179                 p->tex_Texture_Refraction = -1;
1180                 p->tex_Texture_Reflection = -1;
1181                 p->tex_Texture_ShadowMap2D = -1;
1182                 p->tex_Texture_CubeProjection = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1216                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1218                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1219                 CHECKGLERROR
1220                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1221         }
1222         else
1223                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1224
1225         // free the strings
1226         if (vertexstring)
1227                 Mem_Free(vertexstring);
1228         if (geometrystring)
1229                 Mem_Free(geometrystring);
1230         if (fragmentstring)
1231                 Mem_Free(fragmentstring);
1232 }
1233
1234 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1235 {
1236         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1237         if (r_glsl_permutation != perm)
1238         {
1239                 r_glsl_permutation = perm;
1240                 if (!r_glsl_permutation->program)
1241                 {
1242                         if (!r_glsl_permutation->compiled)
1243                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1244                         if (!r_glsl_permutation->program)
1245                         {
1246                                 // remove features until we find a valid permutation
1247                                 int i;
1248                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1249                                 {
1250                                         // reduce i more quickly whenever it would not remove any bits
1251                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1252                                         if (!(permutation & j))
1253                                                 continue;
1254                                         permutation -= j;
1255                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1256                                         if (!r_glsl_permutation->compiled)
1257                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1258                                         if (r_glsl_permutation->program)
1259                                                 break;
1260                                 }
1261                                 if (i >= SHADERPERMUTATION_COUNT)
1262                                 {
1263                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1264                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1265                                         qglUseProgram(0);CHECKGLERROR
1266                                         return; // no bit left to clear, entire mode is broken
1267                                 }
1268                         }
1269                 }
1270                 CHECKGLERROR
1271                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1272         }
1273         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1274         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1275         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1276 }
1277
1278 #ifdef SUPPORTD3D
1279
1280 #ifdef SUPPORTD3D
1281 #include <d3d9.h>
1282 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1283 extern D3DCAPS9 vid_d3d9caps;
1284 #endif
1285
1286 struct r_hlsl_permutation_s;
1287 typedef struct r_hlsl_permutation_s
1288 {
1289         /// hash lookup data
1290         struct r_hlsl_permutation_s *hashnext;
1291         unsigned int mode;
1292         unsigned int permutation;
1293
1294         /// indicates if we have tried compiling this permutation already
1295         qboolean compiled;
1296         /// NULL if compilation failed
1297         IDirect3DVertexShader9 *vertexshader;
1298         IDirect3DPixelShader9 *pixelshader;
1299 }
1300 r_hlsl_permutation_t;
1301
1302 typedef enum D3DVSREGISTER_e
1303 {
1304         D3DVSREGISTER_TexMatrix = 0, // float4x4
1305         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1306         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1307         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1308         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1309         D3DVSREGISTER_ModelToLight = 20, // float4x4
1310         D3DVSREGISTER_EyePosition = 24,
1311         D3DVSREGISTER_FogPlane = 25,
1312         D3DVSREGISTER_LightDir = 26,
1313         D3DVSREGISTER_LightPosition = 27,
1314 }
1315 D3DVSREGISTER_t;
1316
1317 typedef enum D3DPSREGISTER_e
1318 {
1319         D3DPSREGISTER_Alpha = 0,
1320         D3DPSREGISTER_BloomBlur_Parameters = 1,
1321         D3DPSREGISTER_ClientTime = 2,
1322         D3DPSREGISTER_Color_Ambient = 3,
1323         D3DPSREGISTER_Color_Diffuse = 4,
1324         D3DPSREGISTER_Color_Specular = 5,
1325         D3DPSREGISTER_Color_Glow = 6,
1326         D3DPSREGISTER_Color_Pants = 7,
1327         D3DPSREGISTER_Color_Shirt = 8,
1328         D3DPSREGISTER_DeferredColor_Ambient = 9,
1329         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1330         D3DPSREGISTER_DeferredColor_Specular = 11,
1331         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1332         D3DPSREGISTER_DeferredMod_Specular = 13,
1333         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1334         D3DPSREGISTER_EyePosition = 15, // unused
1335         D3DPSREGISTER_FogColor = 16,
1336         D3DPSREGISTER_FogHeightFade = 17,
1337         D3DPSREGISTER_FogPlane = 18,
1338         D3DPSREGISTER_FogPlaneViewDist = 19,
1339         D3DPSREGISTER_FogRangeRecip = 20,
1340         D3DPSREGISTER_LightColor = 21,
1341         D3DPSREGISTER_LightDir = 22, // unused
1342         D3DPSREGISTER_LightPosition = 23,
1343         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1344         D3DPSREGISTER_PixelSize = 25,
1345         D3DPSREGISTER_ReflectColor = 26,
1346         D3DPSREGISTER_ReflectFactor = 27,
1347         D3DPSREGISTER_ReflectOffset = 28,
1348         D3DPSREGISTER_RefractColor = 29,
1349         D3DPSREGISTER_Saturation = 30,
1350         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1351         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1352         D3DPSREGISTER_ScreenToDepth = 33,
1353         D3DPSREGISTER_ShadowMap_Parameters = 34,
1354         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1355         D3DPSREGISTER_SpecularPower = 36,
1356         D3DPSREGISTER_UserVec1 = 37,
1357         D3DPSREGISTER_UserVec2 = 38,
1358         D3DPSREGISTER_UserVec3 = 39,
1359         D3DPSREGISTER_UserVec4 = 40,
1360         D3DPSREGISTER_ViewTintColor = 41,
1361         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1362         D3DPSREGISTER_BloomColorSubtract = 43,
1363         D3DPSREGISTER_ViewToLight = 44, // float4x4
1364         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1365         D3DPSREGISTER_NormalmapScrollBlend = 52,
1366         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1367         D3DPSREGISTER_OffsetMapping_Bias = 54,
1368         // next at 54
1369 }
1370 D3DPSREGISTER_t;
1371
1372 /// information about each possible shader permutation
1373 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1374 /// currently selected permutation
1375 r_hlsl_permutation_t *r_hlsl_permutation;
1376 /// storage for permutations linked in the hash table
1377 memexpandablearray_t r_hlsl_permutationarray;
1378
1379 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1380 {
1381         //unsigned int hashdepth = 0;
1382         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1383         r_hlsl_permutation_t *p;
1384         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1385         {
1386                 if (p->mode == mode && p->permutation == permutation)
1387                 {
1388                         //if (hashdepth > 10)
1389                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1390                         return p;
1391                 }
1392                 //hashdepth++;
1393         }
1394         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1395         p->mode = mode;
1396         p->permutation = permutation;
1397         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1398         r_hlsl_permutationhash[mode][hashindex] = p;
1399         //if (hashdepth > 10)
1400         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1401         return p;
1402 }
1403
1404 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1405 {
1406         char *shaderstring;
1407         if (!filename || !filename[0])
1408                 return NULL;
1409         if (!strcmp(filename, "hlsl/default.hlsl"))
1410         {
1411                 if (!hlslshaderstring)
1412                 {
1413                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1414                         if (hlslshaderstring)
1415                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1416                         else
1417                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1418                 }
1419                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1420                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1421                 return shaderstring;
1422         }
1423         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1424         if (shaderstring)
1425         {
1426                 if (printfromdisknotice)
1427                         Con_DPrintf("from disk %s... ", filename);
1428                 return shaderstring;
1429         }
1430         return shaderstring;
1431 }
1432
1433 #include <d3dx9.h>
1434 //#include <d3dx9shader.h>
1435 //#include <d3dx9mesh.h>
1436
1437 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1438 {
1439         DWORD *vsbin = NULL;
1440         DWORD *psbin = NULL;
1441         fs_offset_t vsbinsize;
1442         fs_offset_t psbinsize;
1443 //      IDirect3DVertexShader9 *vs = NULL;
1444 //      IDirect3DPixelShader9 *ps = NULL;
1445         ID3DXBuffer *vslog = NULL;
1446         ID3DXBuffer *vsbuffer = NULL;
1447         ID3DXConstantTable *vsconstanttable = NULL;
1448         ID3DXBuffer *pslog = NULL;
1449         ID3DXBuffer *psbuffer = NULL;
1450         ID3DXConstantTable *psconstanttable = NULL;
1451         int vsresult = 0;
1452         int psresult = 0;
1453         char temp[MAX_INPUTLINE];
1454         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1455         char vabuf[1024];
1456         qboolean debugshader = gl_paranoid.integer != 0;
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (!debugshader)
1460         {
1461                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1462                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1463         }
1464         if ((!vsbin && vertstring) || (!psbin && fragstring))
1465         {
1466                 const char* dllnames_d3dx9 [] =
1467                 {
1468                         "d3dx9_43.dll",
1469                         "d3dx9_42.dll",
1470                         "d3dx9_41.dll",
1471                         "d3dx9_40.dll",
1472                         "d3dx9_39.dll",
1473                         "d3dx9_38.dll",
1474                         "d3dx9_37.dll",
1475                         "d3dx9_36.dll",
1476                         "d3dx9_35.dll",
1477                         "d3dx9_34.dll",
1478                         "d3dx9_33.dll",
1479                         "d3dx9_32.dll",
1480                         "d3dx9_31.dll",
1481                         "d3dx9_30.dll",
1482                         "d3dx9_29.dll",
1483                         "d3dx9_28.dll",
1484                         "d3dx9_27.dll",
1485                         "d3dx9_26.dll",
1486                         "d3dx9_25.dll",
1487                         "d3dx9_24.dll",
1488                         NULL
1489                 };
1490                 dllhandle_t d3dx9_dll = NULL;
1491                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1493                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 dllfunction_t d3dx9_dllfuncs[] =
1495                 {
1496                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1497                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1498                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1499                         {NULL, NULL}
1500                 };
1501                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1502                 {
1503                         DWORD shaderflags = 0;
1504                         if (debugshader)
1505                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1506                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1507                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1508                         if (vertstring && vertstring[0])
1509                         {
1510                                 if (debugshader)
1511                                 {
1512 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1513 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1514                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1515                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1516                                 }
1517                                 else
1518                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 if (vsbuffer)
1520                                 {
1521                                         vsbinsize = vsbuffer->GetBufferSize();
1522                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1523                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1524                                         vsbuffer->Release();
1525                                 }
1526                                 if (vslog)
1527                                 {
1528                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1529                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1530                                         vslog->Release();
1531                                 }
1532                         }
1533                         if (fragstring && fragstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1538 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1539                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1540                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1541                                 }
1542                                 else
1543                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 if (psbuffer)
1545                                 {
1546                                         psbinsize = psbuffer->GetBufferSize();
1547                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1548                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1549                                         psbuffer->Release();
1550                                 }
1551                                 if (pslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         pslog->Release();
1556                                 }
1557                         }
1558                         Sys_UnloadLibrary(&d3dx9_dll);
1559                 }
1560                 else
1561                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1562         }
1563         if (vsbin && psbin)
1564         {
1565                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1566                 if (FAILED(vsresult))
1567                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1568                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1569                 if (FAILED(psresult))
1570                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1571         }
1572         // free the shader data
1573         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1574         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1575 }
1576
1577 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1578 {
1579         int i;
1580         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1581         int vertstring_length = 0;
1582         int geomstring_length = 0;
1583         int fragstring_length = 0;
1584         char *t;
1585         char *vertexstring, *geometrystring, *fragmentstring;
1586         char *vertstring, *geomstring, *fragstring;
1587         char permutationname[256];
1588         char cachename[256];
1589         int vertstrings_count = 0;
1590         int geomstrings_count = 0;
1591         int fragstrings_count = 0;
1592         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1595
1596         if (p->compiled)
1597                 return;
1598         p->compiled = true;
1599         p->vertexshader = NULL;
1600         p->pixelshader = NULL;
1601
1602         permutationname[0] = 0;
1603         cachename[0] = 0;
1604         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1605         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1606         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1607
1608         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1609         strlcat(cachename, "hlsl/", sizeof(cachename));
1610
1611         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1612         vertstrings_count = 0;
1613         geomstrings_count = 0;
1614         fragstrings_count = 0;
1615         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1616         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1617         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1618
1619         // the first pretext is which type of shader to compile as
1620         // (later these will all be bound together as a program object)
1621         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1622         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1623         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1624
1625         // the second pretext is the mode (for example a light source)
1626         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1627         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1628         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1629         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1630         strlcat(cachename, modeinfo->name, sizeof(cachename));
1631
1632         // now add all the permutation pretexts
1633         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1634         {
1635                 if (permutation & (1<<i))
1636                 {
1637                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1642                 }
1643                 else
1644                 {
1645                         // keep line numbers correct
1646                         vertstrings_list[vertstrings_count++] = "\n";
1647                         geomstrings_list[geomstrings_count++] = "\n";
1648                         fragstrings_list[fragstrings_count++] = "\n";
1649                 }
1650         }
1651
1652         // add static parms
1653         R_CompileShader_AddStaticParms(mode, permutation);
1654         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         vertstrings_count += shaderstaticparms_count;
1656         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         geomstrings_count += shaderstaticparms_count;
1658         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         fragstrings_count += shaderstaticparms_count;
1660
1661         // replace spaces in the cachename with _ characters
1662         for (i = 0;cachename[i];i++)
1663                 if (cachename[i] == ' ')
1664                         cachename[i] = '_';
1665
1666         // now append the shader text itself
1667         vertstrings_list[vertstrings_count++] = vertexstring;
1668         geomstrings_list[geomstrings_count++] = geometrystring;
1669         fragstrings_list[fragstrings_count++] = fragmentstring;
1670
1671         // if any sources were NULL, clear the respective list
1672         if (!vertexstring)
1673                 vertstrings_count = 0;
1674         if (!geometrystring)
1675                 geomstrings_count = 0;
1676         if (!fragmentstring)
1677                 fragstrings_count = 0;
1678
1679         vertstring_length = 0;
1680         for (i = 0;i < vertstrings_count;i++)
1681                 vertstring_length += strlen(vertstrings_list[i]);
1682         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1683         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1684                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1685
1686         geomstring_length = 0;
1687         for (i = 0;i < geomstrings_count;i++)
1688                 geomstring_length += strlen(geomstrings_list[i]);
1689         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1690         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1691                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1692
1693         fragstring_length = 0;
1694         for (i = 0;i < fragstrings_count;i++)
1695                 fragstring_length += strlen(fragstrings_list[i]);
1696         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1697         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1698                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1699
1700         // try to load the cached shader, or generate one
1701         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1702
1703         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1704                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1705         else
1706                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1707
1708         // free the strings
1709         if (vertstring)
1710                 Mem_Free(vertstring);
1711         if (geomstring)
1712                 Mem_Free(geomstring);
1713         if (fragstring)
1714                 Mem_Free(fragstring);
1715         if (vertexstring)
1716                 Mem_Free(vertexstring);
1717         if (geometrystring)
1718                 Mem_Free(geometrystring);
1719         if (fragmentstring)
1720                 Mem_Free(fragmentstring);
1721 }
1722
1723 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1724 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1725 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);}
1726 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);}
1727 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);}
1728 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);}
1729
1730 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1731 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1732 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);}
1733 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);}
1734 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);}
1735 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);}
1736
1737 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1738 {
1739         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1740         if (r_hlsl_permutation != perm)
1741         {
1742                 r_hlsl_permutation = perm;
1743                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1744                 {
1745                         if (!r_hlsl_permutation->compiled)
1746                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                         {
1749                                 // remove features until we find a valid permutation
1750                                 int i;
1751                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1752                                 {
1753                                         // reduce i more quickly whenever it would not remove any bits
1754                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1755                                         if (!(permutation & j))
1756                                                 continue;
1757                                         permutation -= j;
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         if (!r_hlsl_permutation->compiled)
1760                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1762                                                 break;
1763                                 }
1764                                 if (i >= SHADERPERMUTATION_COUNT)
1765                                 {
1766                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         return; // no bit left to clear, entire mode is broken
1769                                 }
1770                         }
1771                 }
1772                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1773                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1774         }
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1777         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1778 }
1779 #endif
1780
1781 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1782 {
1783         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1786         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1787 }
1788
1789 static void R_GLSL_Restart_f(void)
1790 {
1791         unsigned int i, limit;
1792         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1793                 Mem_Free(glslshaderstring);
1794         glslshaderstring = NULL;
1795         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1796                 Mem_Free(hlslshaderstring);
1797         hlslshaderstring = NULL;
1798         switch(vid.renderpath)
1799         {
1800         case RENDERPATH_D3D9:
1801 #ifdef SUPPORTD3D
1802                 {
1803                         r_hlsl_permutation_t *p;
1804                         r_hlsl_permutation = NULL;
1805                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1806                         for (i = 0;i < limit;i++)
1807                         {
1808                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1809                                 {
1810                                         if (p->vertexshader)
1811                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1812                                         if (p->pixelshader)
1813                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1814                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1815                                 }
1816                         }
1817                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1818                 }
1819 #endif
1820                 break;
1821         case RENDERPATH_D3D10:
1822                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1823                 break;
1824         case RENDERPATH_D3D11:
1825                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_GL20:
1828         case RENDERPATH_GLES2:
1829                 {
1830                         r_glsl_permutation_t *p;
1831                         r_glsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1836                                 {
1837                                         GL_Backend_FreeProgram(p->program);
1838                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1842                 }
1843                 break;
1844         case RENDERPATH_GL11:
1845         case RENDERPATH_GL13:
1846         case RENDERPATH_GLES1:
1847                 break;
1848         case RENDERPATH_SOFT:
1849                 break;
1850         }
1851 }
1852
1853 static void R_GLSL_DumpShader_f(void)
1854 {
1855         int i;
1856         qfile_t *file;
1857
1858         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1859         if (file)
1860         {
1861                 FS_Print(file, "/* The engine may define the following macros:\n");
1862                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1863                 for (i = 0;i < SHADERMODE_COUNT;i++)
1864                         FS_Print(file, glslshadermodeinfo[i].pretext);
1865                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1866                         FS_Print(file, shaderpermutationinfo[i].pretext);
1867                 FS_Print(file, "*/\n");
1868                 FS_Print(file, builtinshaderstring);
1869                 FS_Close(file);
1870                 Con_Printf("glsl/default.glsl written\n");
1871         }
1872         else
1873                 Con_Printf("failed to write to glsl/default.glsl\n");
1874
1875         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1876         if (file)
1877         {
1878                 FS_Print(file, "/* The engine may define the following macros:\n");
1879                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1880                 for (i = 0;i < SHADERMODE_COUNT;i++)
1881                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1882                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                         FS_Print(file, shaderpermutationinfo[i].pretext);
1884                 FS_Print(file, "*/\n");
1885                 FS_Print(file, builtinhlslshaderstring);
1886                 FS_Close(file);
1887                 Con_Printf("hlsl/default.hlsl written\n");
1888         }
1889         else
1890                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1891 }
1892
1893 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1894 {
1895         unsigned int permutation = 0;
1896         if (r_trippy.integer && !notrippy)
1897                 permutation |= SHADERPERMUTATION_TRIPPY;
1898         permutation |= SHADERPERMUTATION_VIEWTINT;
1899         if (first)
1900                 permutation |= SHADERPERMUTATION_DIFFUSE;
1901         if (second)
1902                 permutation |= SHADERPERMUTATION_SPECULAR;
1903         if (texturemode == GL_MODULATE)
1904                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1905         else if (texturemode == GL_ADD)
1906                 permutation |= SHADERPERMUTATION_GLOW;
1907         else if (texturemode == GL_DECAL)
1908                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1909         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1910                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1911         if (suppresstexalpha)
1912                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1913         if (!second)
1914                 texturemode = GL_MODULATE;
1915         if (vid.allowalphatocoverage)
1916                 GL_AlphaToCoverage(false);
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1922                 R_Mesh_TexBind(GL20TU_FIRST , first );
1923                 R_Mesh_TexBind(GL20TU_SECOND, second);
1924                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1925                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1926 #endif
1927                 break;
1928         case RENDERPATH_D3D10:
1929                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_D3D11:
1932                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933                 break;
1934         case RENDERPATH_GL20:
1935         case RENDERPATH_GLES2:
1936                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1938                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1939                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941                 break;
1942         case RENDERPATH_GL13:
1943         case RENDERPATH_GLES1:
1944                 R_Mesh_TexBind(0, first );
1945                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946                 R_Mesh_TexBind(1, second);
1947                 if (second)
1948                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, first );
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955                 R_Mesh_TexBind(GL20TU_FIRST , first );
1956                 R_Mesh_TexBind(GL20TU_SECOND, second);
1957                 break;
1958         }
1959 }
1960
1961 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1962 {
1963         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1964 }
1965
1966 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1967 {
1968         unsigned int permutation = 0;
1969         if (r_trippy.integer && !notrippy)
1970                 permutation |= SHADERPERMUTATION_TRIPPY;
1971         if (depthrgb)
1972                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1973         if (vid.allowalphatocoverage)
1974                 GL_AlphaToCoverage(false);
1975         switch (vid.renderpath)
1976         {
1977         case RENDERPATH_D3D9:
1978 #ifdef SUPPORTD3D
1979                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980 #endif
1981                 break;
1982         case RENDERPATH_D3D10:
1983                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1984                 break;
1985         case RENDERPATH_D3D11:
1986                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1987                 break;
1988         case RENDERPATH_GL20:
1989         case RENDERPATH_GLES2:
1990                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1991                 break;
1992         case RENDERPATH_GL13:
1993         case RENDERPATH_GLES1:
1994                 R_Mesh_TexBind(0, 0);
1995                 R_Mesh_TexBind(1, 0);
1996                 break;
1997         case RENDERPATH_GL11:
1998                 R_Mesh_TexBind(0, 0);
1999                 break;
2000         case RENDERPATH_SOFT:
2001                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2002                 break;
2003         }
2004 }
2005
2006 void R_SetupShader_ShowDepth(qboolean notrippy)
2007 {
2008         int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         if (vid.allowalphatocoverage)
2012                 GL_AlphaToCoverage(false);
2013         switch (vid.renderpath)
2014         {
2015         case RENDERPATH_D3D9:
2016 #ifdef SUPPORTHLSL
2017                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2018 #endif
2019                 break;
2020         case RENDERPATH_D3D10:
2021                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2022                 break;
2023         case RENDERPATH_D3D11:
2024                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2025                 break;
2026         case RENDERPATH_GL20:
2027         case RENDERPATH_GLES2:
2028                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2029                 break;
2030         case RENDERPATH_GL13:
2031         case RENDERPATH_GLES1:
2032                 break;
2033         case RENDERPATH_GL11:
2034                 break;
2035         case RENDERPATH_SOFT:
2036                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2037                 break;
2038         }
2039 }
2040
2041 extern qboolean r_shadow_usingdeferredprepass;
2042 extern rtexture_t *r_shadow_attenuationgradienttexture;
2043 extern rtexture_t *r_shadow_attenuation2dtexture;
2044 extern rtexture_t *r_shadow_attenuation3dtexture;
2045 extern qboolean r_shadow_usingshadowmap2d;
2046 extern qboolean r_shadow_usingshadowmaportho;
2047 extern float r_shadow_shadowmap_texturescale[2];
2048 extern float r_shadow_shadowmap_parameters[4];
2049 extern qboolean r_shadow_shadowmapvsdct;
2050 extern qboolean r_shadow_shadowmapsampler;
2051 extern int r_shadow_shadowmappcf;
2052 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2053 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2054 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2055 extern matrix4x4_t r_shadow_shadowmapmatrix;
2056 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2057 extern int r_shadow_prepass_width;
2058 extern int r_shadow_prepass_height;
2059 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2060 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2061 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2062 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2063
2064 #define BLENDFUNC_ALLOWS_COLORMOD      1
2065 #define BLENDFUNC_ALLOWS_FOG           2
2066 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2067 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2068 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2069 static int R_BlendFuncFlags(int src, int dst)
2070 {
2071         int r = 0;
2072
2073         // a blendfunc allows colormod if:
2074         // a) it can never keep the destination pixel invariant, or
2075         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2076         // this is to prevent unintended side effects from colormod
2077
2078         // a blendfunc allows fog if:
2079         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2080         // this is to prevent unintended side effects from fog
2081
2082         // these checks are the output of fogeval.pl
2083
2084         r |= BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2094         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2097         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2106
2107         return r;
2108 }
2109
2110 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)
2111 {
2112         // select a permutation of the lighting shader appropriate to this
2113         // combination of texture, entity, light source, and fogging, only use the
2114         // minimum features necessary to avoid wasting rendering time in the
2115         // fragment shader on features that are not being used
2116         unsigned int permutation = 0;
2117         unsigned int mode = 0;
2118         int blendfuncflags;
2119         static float dummy_colormod[3] = {1, 1, 1};
2120         float *colormod = rsurface.colormod;
2121         float m16f[16];
2122         matrix4x4_t tempmatrix;
2123         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2124         if (r_trippy.integer && !notrippy)
2125                 permutation |= SHADERPERMUTATION_TRIPPY;
2126         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2127                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2128         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2129                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2130         if (rsurfacepass == RSURFPASS_BACKGROUND)
2131         {
2132                 // distorted background
2133                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2134                 {
2135                         mode = SHADERMODE_WATER;
2136                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2137                         {
2138                                 // this is the right thing to do for wateralpha
2139                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2140                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2141                         }
2142                         else
2143                         {
2144                                 // this is the right thing to do for entity alpha
2145                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                         }
2148                 }
2149                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2150                 {
2151                         mode = SHADERMODE_REFRACTION;
2152                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                 }
2155                 else
2156                 {
2157                         mode = SHADERMODE_GENERIC;
2158                         permutation |= SHADERPERMUTATION_DIFFUSE;
2159                         GL_BlendFunc(GL_ONE, GL_ZERO);
2160                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161                 }
2162                 if (vid.allowalphatocoverage)
2163                         GL_AlphaToCoverage(false);
2164         }
2165         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2166         {
2167                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2168                 {
2169                         switch(rsurface.texture->offsetmapping)
2170                         {
2171                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2172                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2173                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_OFF: break;
2175                         }
2176                 }
2177                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179                 // normalmap (deferred prepass), may use alpha test on diffuse
2180                 mode = SHADERMODE_DEFERREDGEOMETRY;
2181                 GL_BlendFunc(GL_ONE, GL_ZERO);
2182                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2183                 if (vid.allowalphatocoverage)
2184                         GL_AlphaToCoverage(false);
2185         }
2186         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2187         {
2188                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2189                 {
2190                         switch(rsurface.texture->offsetmapping)
2191                         {
2192                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2193                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_OFF: break;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // light source
2201                 mode = SHADERMODE_LIGHTSOURCE;
2202                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2203                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2204                 if (diffusescale > 0)
2205                         permutation |= SHADERPERMUTATION_DIFFUSE;
2206                 if (specularscale > 0)
2207                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2208                 if (r_refdef.fogenabled)
2209                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2210                 if (rsurface.texture->colormapping)
2211                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2212                 if (r_shadow_usingshadowmap2d)
2213                 {
2214                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2215                         if(r_shadow_shadowmapvsdct)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2217
2218                         if (r_shadow_shadowmapsampler)
2219                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2220                         if (r_shadow_shadowmappcf > 1)
2221                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2222                         else if (r_shadow_shadowmappcf)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2224                         if (r_shadow_shadowmap2ddepthbuffer)
2225                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2226                 }
2227                 if (rsurface.texture->reflectmasktexture)
2228                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2229                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2230                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2231                 if (vid.allowalphatocoverage)
2232                         GL_AlphaToCoverage(false);
2233         }
2234         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2235         {
2236                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2237                 {
2238                         switch(rsurface.texture->offsetmapping)
2239                         {
2240                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2241                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2243                         case OFFSETMAPPING_OFF: break;
2244                         }
2245                 }
2246                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2247                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2248                 // unshaded geometry (fullbright or ambient model lighting)
2249                 mode = SHADERMODE_FLATCOLOR;
2250                 ambientscale = diffusescale = specularscale = 0;
2251                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2252                         permutation |= SHADERPERMUTATION_GLOW;
2253                 if (r_refdef.fogenabled)
2254                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2255                 if (rsurface.texture->colormapping)
2256                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2257                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2258                 {
2259                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2260                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2261
2262                         if (r_shadow_shadowmapsampler)
2263                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2264                         if (r_shadow_shadowmappcf > 1)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2266                         else if (r_shadow_shadowmappcf)
2267                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2268                         if (r_shadow_shadowmap2ddepthbuffer)
2269                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2270                 }
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2272                         permutation |= SHADERPERMUTATION_REFLECTION;
2273                 if (rsurface.texture->reflectmasktexture)
2274                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2275                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2276                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2277                 // when using alphatocoverage, we don't need alphakill
2278                 if (vid.allowalphatocoverage)
2279                 {
2280                         if (r_transparent_alphatocoverage.integer)
2281                         {
2282                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2283                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2284                         }
2285                         else
2286                                 GL_AlphaToCoverage(false);
2287                 }
2288         }
2289         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2290         {
2291                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2292                 {
2293                         switch(rsurface.texture->offsetmapping)
2294                         {
2295                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2296                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2297                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2298                         case OFFSETMAPPING_OFF: break;
2299                         }
2300                 }
2301                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2302                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2303                 // directional model lighting
2304                 mode = SHADERMODE_LIGHTDIRECTION;
2305                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2306                         permutation |= SHADERPERMUTATION_GLOW;
2307                 permutation |= SHADERPERMUTATION_DIFFUSE;
2308                 if (specularscale > 0)
2309                         permutation |= SHADERPERMUTATION_SPECULAR;
2310                 if (r_refdef.fogenabled)
2311                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2312                 if (rsurface.texture->colormapping)
2313                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2314                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2315                 {
2316                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2317                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2318
2319                         if (r_shadow_shadowmapsampler)
2320                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2321                         if (r_shadow_shadowmappcf > 1)
2322                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2323                         else if (r_shadow_shadowmappcf)
2324                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2325                         if (r_shadow_shadowmap2ddepthbuffer)
2326                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2327                 }
2328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2329                         permutation |= SHADERPERMUTATION_REFLECTION;
2330                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2331                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2332                 if (rsurface.texture->reflectmasktexture)
2333                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2335                 {
2336                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2337                         if (r_shadow_bouncegriddirectional)
2338                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2339                 }
2340                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2341                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 // when using alphatocoverage, we don't need alphakill
2343                 if (vid.allowalphatocoverage)
2344                 {
2345                         if (r_transparent_alphatocoverage.integer)
2346                         {
2347                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2348                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2349                         }
2350                         else
2351                                 GL_AlphaToCoverage(false);
2352                 }
2353         }
2354         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2355         {
2356                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2357                 {
2358                         switch(rsurface.texture->offsetmapping)
2359                         {
2360                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2361                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2362                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_OFF: break;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // ambient model lighting
2369                 mode = SHADERMODE_LIGHTDIRECTION;
2370                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371                         permutation |= SHADERPERMUTATION_GLOW;
2372                 if (r_refdef.fogenabled)
2373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374                 if (rsurface.texture->colormapping)
2375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377                 {
2378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380
2381                         if (r_shadow_shadowmapsampler)
2382                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2383                         if (r_shadow_shadowmappcf > 1)
2384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2385                         else if (r_shadow_shadowmappcf)
2386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387                         if (r_shadow_shadowmap2ddepthbuffer)
2388                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2389                 }
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2391                         permutation |= SHADERPERMUTATION_REFLECTION;
2392                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2393                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2394                 if (rsurface.texture->reflectmasktexture)
2395                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2396                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2397                 {
2398                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2399                         if (r_shadow_bouncegriddirectional)
2400                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2401                 }
2402                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404                 // when using alphatocoverage, we don't need alphakill
2405                 if (vid.allowalphatocoverage)
2406                 {
2407                         if (r_transparent_alphatocoverage.integer)
2408                         {
2409                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2410                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2411                         }
2412                         else
2413                                 GL_AlphaToCoverage(false);
2414                 }
2415         }
2416         else
2417         {
2418                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2419                 {
2420                         switch(rsurface.texture->offsetmapping)
2421                         {
2422                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2423                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2425                         case OFFSETMAPPING_OFF: break;
2426                         }
2427                 }
2428                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2429                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2430                 // lightmapped wall
2431                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2432                         permutation |= SHADERPERMUTATION_GLOW;
2433                 if (r_refdef.fogenabled)
2434                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2435                 if (rsurface.texture->colormapping)
2436                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2437                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2438                 {
2439                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2440                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2441
2442                         if (r_shadow_shadowmapsampler)
2443                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2444                         if (r_shadow_shadowmappcf > 1)
2445                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2446                         else if (r_shadow_shadowmappcf)
2447                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2448                         if (r_shadow_shadowmap2ddepthbuffer)
2449                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2450                 }
2451                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2452                         permutation |= SHADERPERMUTATION_REFLECTION;
2453                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2454                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2455                 if (rsurface.texture->reflectmasktexture)
2456                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2457                 if (FAKELIGHT_ENABLED)
2458                 {
2459                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2460                         mode = SHADERMODE_FAKELIGHT;
2461                         permutation |= SHADERPERMUTATION_DIFFUSE;
2462                         if (specularscale > 0)
2463                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2464                 }
2465                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2466                 {
2467                         // deluxemapping (light direction texture)
2468                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2470                         else
2471                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (r_glsl_deluxemapping.integer >= 2)
2477                 {
2478                         // fake deluxemapping (uniform light direction in tangentspace)
2479                         if (rsurface.uselightmaptexture)
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2481                         else
2482                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2483                         permutation |= SHADERPERMUTATION_DIFFUSE;
2484                         if (specularscale > 0)
2485                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2486                 }
2487                 else if (rsurface.uselightmaptexture)
2488                 {
2489                         // ordinary lightmapping (q1bsp, q3bsp)
2490                         mode = SHADERMODE_LIGHTMAP;
2491                 }
2492                 else
2493                 {
2494                         // ordinary vertex coloring (q3bsp)
2495                         mode = SHADERMODE_VERTEXCOLOR;
2496                 }
2497                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2498                 {
2499                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2500                         if (r_shadow_bouncegriddirectional)
2501                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2502                 }
2503                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2504                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2505                 // when using alphatocoverage, we don't need alphakill
2506                 if (vid.allowalphatocoverage)
2507                 {
2508                         if (r_transparent_alphatocoverage.integer)
2509                         {
2510                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2511                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2512                         }
2513                         else
2514                                 GL_AlphaToCoverage(false);
2515                 }
2516         }
2517         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2518                 colormod = dummy_colormod;
2519         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2520                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2521         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2522                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2523         switch(vid.renderpath)
2524         {
2525         case RENDERPATH_D3D9:
2526 #ifdef SUPPORTD3D
2527                 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);
2528                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2529                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2530                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2531                 if (mode == SHADERMODE_LIGHTSOURCE)
2532                 {
2533                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2534                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2535                 }
2536                 else
2537                 {
2538                         if (mode == SHADERMODE_LIGHTDIRECTION)
2539                         {
2540                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2541                         }
2542                 }
2543                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2544                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2545                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2546                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2547                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2548
2549                 if (mode == SHADERMODE_LIGHTSOURCE)
2550                 {
2551                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2553                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2554                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2555                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2556
2557                         // additive passes are only darkened by fog, not tinted
2558                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2559                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2560                 }
2561                 else
2562                 {
2563                         if (mode == SHADERMODE_FLATCOLOR)
2564                         {
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2566                         }
2567                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2568                         {
2569                                 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]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2571                                 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);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2574                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2576                         }
2577                         else
2578                         {
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2581                                 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);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2584                         }
2585                         // additive passes are only darkened by fog, not tinted
2586                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2588                         else
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2590                         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);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2592                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2593                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2594                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2595                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2596                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2597                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2598                         if (mode == SHADERMODE_WATER)
2599                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2600                 }
2601                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2602                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2603                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2604                 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));
2605                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2606                 if (rsurface.texture->pantstexture)
2607                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2608                 else
2609                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2610                 if (rsurface.texture->shirttexture)
2611                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2612                 else
2613                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2614                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2616                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2617                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2618                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2619                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2620                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2621                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2622                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2623                         );
2624                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2626                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2627                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2628
2629                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2630                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2631                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2632                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2634                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2635                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2636                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2637                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2638                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2639                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2640                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2641                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2642                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2643                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2644                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2645                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2646                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2647                 {
2648                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2649                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2650                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2651                 }
2652                 else
2653                 {
2654                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2655                 }
2656 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2657                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2658                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2659                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2660                 {
2661                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2662                         if (rsurface.rtlight)
2663                         {
2664                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2665                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2666                         }
2667                 }
2668 #endif
2669                 break;
2670         case RENDERPATH_D3D10:
2671                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672                 break;
2673         case RENDERPATH_D3D11:
2674                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2675                 break;
2676         case RENDERPATH_GL20:
2677         case RENDERPATH_GLES2:
2678                 if (!vid.useinterleavedarrays)
2679                 {
2680                         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);
2681                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2682                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2684                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2685                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2686                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2687                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2688                 }
2689                 else
2690                 {
2691                         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);
2692                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2693                 }
2694                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2695                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2696                 if (mode == SHADERMODE_LIGHTSOURCE)
2697                 {
2698                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2699                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2700                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2701                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2702                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2703                         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);
2704         
2705                         // additive passes are only darkened by fog, not tinted
2706                         if (r_glsl_permutation->loc_FogColor >= 0)
2707                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2708                         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);
2709                 }
2710                 else
2711                 {
2712                         if (mode == SHADERMODE_FLATCOLOR)
2713                         {
2714                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2715                         }
2716                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2717                         {
2718                                 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]);
2719                                 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]);
2720                                 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);
2721                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2722                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2723                                 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]);
2724                                 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]);
2725                         }
2726                         else
2727                         {
2728                                 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]);
2729                                 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]);
2730                                 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);
2731                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2732                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2733                         }
2734                         // additive passes are only darkened by fog, not tinted
2735                         if (r_glsl_permutation->loc_FogColor >= 0)
2736                         {
2737                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2738                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2739                                 else
2740                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2741                         }
2742                         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);
2743                         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]);
2744                         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]);
2745                         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]);
2746                         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]);
2747                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2748                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2749                         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);
2750                         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]);
2751                 }
2752                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2753                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2754                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2755                 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]);
2756                 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]);
2757
2758                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2759                 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));
2760                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2761                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2762                 {
2763                         if (rsurface.texture->pantstexture)
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2765                         else
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2767                 }
2768                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2769                 {
2770                         if (rsurface.texture->shirttexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2774                 }
2775                 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]);
2776                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2777                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2778                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2779                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2780                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2781                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2782                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2783                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2784                         );
2785                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2786                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2787                 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]);
2788                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2789                 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);}
2790                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2791
2792                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2793                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2794                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2795                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2796                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2797                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2798                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2799                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2800                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2801                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2802                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2803                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2804                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2805                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2806                 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);
2807                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2808                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2809                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2810                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2811                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2812                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2813                 {
2814                         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);
2815                         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);
2816                         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);
2817                 }
2818                 else
2819                 {
2820                         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);
2821                 }
2822                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2823                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2824                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2825                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2826                 {
2827                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2828                         if (rsurface.rtlight)
2829                         {
2830                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2831                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2832                         }
2833                 }
2834                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2835                 CHECKGLERROR
2836                 break;
2837         case RENDERPATH_GL11:
2838         case RENDERPATH_GL13:
2839         case RENDERPATH_GLES1:
2840                 break;
2841         case RENDERPATH_SOFT:
2842                 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);
2843                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2844                 R_SetupShader_SetPermutationSoft(mode, permutation);
2845                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2846                 if (mode == SHADERMODE_LIGHTSOURCE)
2847                 {
2848                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2852                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2854         
2855                         // additive passes are only darkened by fog, not tinted
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2857                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2858                 }
2859                 else
2860                 {
2861                         if (mode == SHADERMODE_FLATCOLOR)
2862                         {
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2864                         }
2865                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2866                         {
2867                                 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]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2869                                 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);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2872                                 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]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2874                         }
2875                         else
2876                         {
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2879                                 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);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2882                         }
2883                         // additive passes are only darkened by fog, not tinted
2884                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2886                         else
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2888                         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);
2889                         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]);
2890                         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]);
2891                         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]);
2892                         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]);
2893                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2894                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2895                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2896                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2897                 }
2898                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2899                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2900                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2901                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2902                 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]);
2903
2904                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2905                 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));
2906                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2907                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2908                 {
2909                         if (rsurface.texture->pantstexture)
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2911                         else
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2913                 }
2914                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2915                 {
2916                         if (rsurface.texture->shirttexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2920                 }
2921                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2925                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2926                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2927                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2928                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2929                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2930                         );
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2933                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2934                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2935
2936                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2937                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2938                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2939                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2940                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2941                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2942                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2943                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2944                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2945                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2946                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2947                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2948                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2949                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2950                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2951                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2952                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2953                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2954                 {
2955                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2956                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2957                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2958                 }
2959                 else
2960                 {
2961                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2962                 }
2963 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2964                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2965                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2966                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2967                 {
2968                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2969                         if (rsurface.rtlight)
2970                         {
2971                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2972                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2973                         }
2974                 }
2975                 break;
2976         }
2977 }
2978
2979 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2980 {
2981         // select a permutation of the lighting shader appropriate to this
2982         // combination of texture, entity, light source, and fogging, only use the
2983         // minimum features necessary to avoid wasting rendering time in the
2984         // fragment shader on features that are not being used
2985         unsigned int permutation = 0;
2986         unsigned int mode = 0;
2987         const float *lightcolorbase = rtlight->currentcolor;
2988         float ambientscale = rtlight->ambientscale;
2989         float diffusescale = rtlight->diffusescale;
2990         float specularscale = rtlight->specularscale;
2991         // this is the location of the light in view space
2992         vec3_t viewlightorigin;
2993         // this transforms from view space (camera) to light space (cubemap)
2994         matrix4x4_t viewtolight;
2995         matrix4x4_t lighttoview;
2996         float viewtolight16f[16];
2997         // light source
2998         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2999         if (rtlight->currentcubemap != r_texture_whitecube)
3000                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3001         if (diffusescale > 0)
3002                 permutation |= SHADERPERMUTATION_DIFFUSE;
3003         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3004                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3005         if (r_shadow_usingshadowmap2d)
3006         {
3007                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3008                 if (r_shadow_shadowmapvsdct)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3010
3011                 if (r_shadow_shadowmapsampler)
3012                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3013                 if (r_shadow_shadowmappcf > 1)
3014                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3015                 else if (r_shadow_shadowmappcf)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3017                 if (r_shadow_shadowmap2ddepthbuffer)
3018                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3019         }
3020         if (vid.allowalphatocoverage)
3021                 GL_AlphaToCoverage(false);
3022         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3023         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3024         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3025         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3026         switch(vid.renderpath)
3027         {
3028         case RENDERPATH_D3D9:
3029 #ifdef SUPPORTD3D
3030                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3031                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3032                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3036                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3037                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3038                 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);
3039                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3040                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3041
3042                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3043                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3044                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3045                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3046                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3047 #endif
3048                 break;
3049         case RENDERPATH_D3D10:
3050                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3051                 break;
3052         case RENDERPATH_D3D11:
3053                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3054                 break;
3055         case RENDERPATH_GL20:
3056         case RENDERPATH_GLES2:
3057                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3060                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3061                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3062                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3063                 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]);
3064                 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]);
3065                 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);
3066                 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]);
3067                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3068
3069                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3070                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3071                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3072                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3073                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3074                 break;
3075         case RENDERPATH_GL11:
3076         case RENDERPATH_GL13:
3077         case RENDERPATH_GLES1:
3078                 break;
3079         case RENDERPATH_SOFT:
3080                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3081                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3082                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3086                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3087                 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]);
3088                 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);
3089                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3090                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3091
3092                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3093                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3094                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3095                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3096                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3097                 break;
3098         }
3099 }
3100
3101 #define SKINFRAME_HASH 1024
3102
3103 typedef struct
3104 {
3105         int loadsequence; // incremented each level change
3106         memexpandablearray_t array;
3107         skinframe_t *hash[SKINFRAME_HASH];
3108 }
3109 r_skinframe_t;
3110 r_skinframe_t r_skinframe;
3111
3112 void R_SkinFrame_PrepareForPurge(void)
3113 {
3114         r_skinframe.loadsequence++;
3115         // wrap it without hitting zero
3116         if (r_skinframe.loadsequence >= 200)
3117                 r_skinframe.loadsequence = 1;
3118 }
3119
3120 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3121 {
3122         if (!skinframe)
3123                 return;
3124         // mark the skinframe as used for the purging code
3125         skinframe->loadsequence = r_skinframe.loadsequence;
3126 }
3127
3128 void R_SkinFrame_Purge(void)
3129 {
3130         int i;
3131         skinframe_t *s;
3132         for (i = 0;i < SKINFRAME_HASH;i++)
3133         {
3134                 for (s = r_skinframe.hash[i];s;s = s->next)
3135                 {
3136                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3137                         {
3138                                 if (s->merged == s->base)
3139                                         s->merged = NULL;
3140                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3141                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3142                                 R_PurgeTexture(s->merged);s->merged = NULL;
3143                                 R_PurgeTexture(s->base  );s->base   = NULL;
3144                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3145                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3146                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3147                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3148                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3149                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3150                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3151                                 s->loadsequence = 0;
3152                         }
3153                 }
3154         }
3155 }
3156
3157 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3158         skinframe_t *item;
3159         char basename[MAX_QPATH];
3160
3161         Image_StripImageExtension(name, basename, sizeof(basename));
3162
3163         if( last == NULL ) {
3164                 int hashindex;
3165                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3166                 item = r_skinframe.hash[hashindex];
3167         } else {
3168                 item = last->next;
3169         }
3170
3171         // linearly search through the hash bucket
3172         for( ; item ; item = item->next ) {
3173                 if( !strcmp( item->basename, basename ) ) {
3174                         return item;
3175                 }
3176         }
3177         return NULL;
3178 }
3179
3180 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3181 {
3182         skinframe_t *item;
3183         int hashindex;
3184         char basename[MAX_QPATH];
3185
3186         Image_StripImageExtension(name, basename, sizeof(basename));
3187
3188         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3189         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3190                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3191                         break;
3192
3193         if (!item) {
3194                 rtexture_t *dyntexture;
3195                 // check whether its a dynamic texture
3196                 dyntexture = CL_GetDynTexture( basename );
3197                 if (!add && !dyntexture)
3198                         return NULL;
3199                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3200                 memset(item, 0, sizeof(*item));
3201                 strlcpy(item->basename, basename, sizeof(item->basename));
3202                 item->base = dyntexture; // either NULL or dyntexture handle
3203                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3204                 item->comparewidth = comparewidth;
3205                 item->compareheight = compareheight;
3206                 item->comparecrc = comparecrc;
3207                 item->next = r_skinframe.hash[hashindex];
3208                 r_skinframe.hash[hashindex] = item;
3209         }
3210         else if (textureflags & TEXF_FORCE_RELOAD)
3211         {
3212                 rtexture_t *dyntexture;
3213                 // check whether its a dynamic texture
3214                 dyntexture = CL_GetDynTexture( basename );
3215                 if (!add && !dyntexture)
3216                         return NULL;
3217                 if (item->merged == item->base)
3218                         item->merged = NULL;
3219                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3220                 R_PurgeTexture(item->stain );item->stain  = NULL;
3221                 R_PurgeTexture(item->merged);item->merged = NULL;
3222                 R_PurgeTexture(item->base  );item->base   = NULL;
3223                 R_PurgeTexture(item->pants );item->pants  = NULL;
3224                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3225                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3226                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3227                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3228                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3229         R_PurgeTexture(item->reflect);item->reflect = NULL;
3230                 item->loadsequence = 0;
3231         }
3232         else if( item->base == NULL )
3233         {
3234                 rtexture_t *dyntexture;
3235                 // check whether its a dynamic texture
3236                 // 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]
3237                 dyntexture = CL_GetDynTexture( basename );
3238                 item->base = dyntexture; // either NULL or dyntexture handle
3239         }
3240
3241         R_SkinFrame_MarkUsed(item);
3242         return item;
3243 }
3244
3245 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3246         { \
3247                 unsigned long long avgcolor[5], wsum; \
3248                 int pix, comp, w; \
3249                 avgcolor[0] = 0; \
3250                 avgcolor[1] = 0; \
3251                 avgcolor[2] = 0; \
3252                 avgcolor[3] = 0; \
3253                 avgcolor[4] = 0; \
3254                 wsum = 0; \
3255                 for(pix = 0; pix < cnt; ++pix) \
3256                 { \
3257                         w = 0; \
3258                         for(comp = 0; comp < 3; ++comp) \
3259                                 w += getpixel; \
3260                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3261                         { \
3262                                 ++wsum; \
3263                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3264                                 w = getpixel; \
3265                                 for(comp = 0; comp < 3; ++comp) \
3266                                         avgcolor[comp] += getpixel * w; \
3267                                 avgcolor[3] += w; \
3268                         } \
3269                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3270                         avgcolor[4] += getpixel; \
3271                 } \
3272                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3273                         avgcolor[3] = 1; \
3274                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3275                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3276                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3278         }
3279
3280 extern cvar_t gl_picmip;
3281 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3282 {
3283         int j;
3284         unsigned char *pixels;
3285         unsigned char *bumppixels;
3286         unsigned char *basepixels = NULL;
3287         int basepixels_width = 0;
3288         int basepixels_height = 0;
3289         skinframe_t *skinframe;
3290         rtexture_t *ddsbase = NULL;
3291         qboolean ddshasalpha = false;
3292         float ddsavgcolor[4];
3293         char basename[MAX_QPATH];
3294         int miplevel = R_PicmipForFlags(textureflags);
3295         int savemiplevel = miplevel;
3296         int mymiplevel;
3297         char vabuf[1024];
3298
3299         if (cls.state == ca_dedicated)
3300                 return NULL;
3301
3302         // return an existing skinframe if already loaded
3303         // if loading of the first image fails, don't make a new skinframe as it
3304         // would cause all future lookups of this to be missing
3305         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3306         if (skinframe && skinframe->base)
3307                 return skinframe;
3308
3309         Image_StripImageExtension(name, basename, sizeof(basename));
3310
3311         // check for DDS texture file first
3312         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3313         {
3314                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3315                 if (basepixels == NULL)
3316                         return NULL;
3317         }
3318
3319         // FIXME handle miplevel
3320
3321         if (developer_loading.integer)
3322                 Con_Printf("loading skin \"%s\"\n", name);
3323
3324         // we've got some pixels to store, so really allocate this new texture now
3325         if (!skinframe)
3326                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3327         textureflags &= ~TEXF_FORCE_RELOAD;
3328         skinframe->stain = NULL;
3329         skinframe->merged = NULL;
3330         skinframe->base = NULL;
3331         skinframe->pants = NULL;
3332         skinframe->shirt = NULL;
3333         skinframe->nmap = NULL;
3334         skinframe->gloss = NULL;
3335         skinframe->glow = NULL;
3336         skinframe->fog = NULL;
3337         skinframe->reflect = NULL;
3338         skinframe->hasalpha = false;
3339
3340         if (ddsbase)
3341         {
3342                 skinframe->base = ddsbase;
3343                 skinframe->hasalpha = ddshasalpha;
3344                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3345                 if (r_loadfog && skinframe->hasalpha)
3346                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3347                 //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]);
3348         }
3349         else
3350         {
3351                 basepixels_width = image_width;
3352                 basepixels_height = image_height;
3353                 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);
3354                 if (textureflags & TEXF_ALPHA)
3355                 {
3356                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3357                         {
3358                                 if (basepixels[j] < 255)
3359                                 {
3360                                         skinframe->hasalpha = true;
3361                                         break;
3362                                 }
3363                         }
3364                         if (r_loadfog && skinframe->hasalpha)
3365                         {
3366                                 // has transparent pixels
3367                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3368                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3369                                 {
3370                                         pixels[j+0] = 255;
3371                                         pixels[j+1] = 255;
3372                                         pixels[j+2] = 255;
3373                                         pixels[j+3] = basepixels[j+3];
3374                                 }
3375                                 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);
3376                                 Mem_Free(pixels);
3377                         }
3378                 }
3379                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3380 #ifndef USE_GLES2
3381                 //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]);
3382                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3383                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3385                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3386 #endif
3387         }
3388
3389         if (r_loaddds)
3390         {
3391                 mymiplevel = savemiplevel;
3392                 if (r_loadnormalmap)
3393                         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);
3394                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3395                 if (r_loadgloss)
3396                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3397                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3398                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3399                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3400         }
3401
3402         // _norm is the name used by tenebrae and has been adopted as standard
3403         if (r_loadnormalmap && skinframe->nmap == NULL)
3404         {
3405                 mymiplevel = savemiplevel;
3406                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3407                 {
3408                         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);
3409                         Mem_Free(pixels);
3410                         pixels = NULL;
3411                 }
3412                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3413                 {
3414                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3415                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3416                         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);
3417                         Mem_Free(pixels);
3418                         Mem_Free(bumppixels);
3419                 }
3420                 else if (r_shadow_bumpscale_basetexture.value > 0)
3421                 {
3422                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3423                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3424                         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);
3425                         Mem_Free(pixels);
3426                 }
3427 #ifndef USE_GLES2
3428                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3429                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3430 #endif
3431         }
3432
3433         // _luma is supported only for tenebrae compatibility
3434         // _glow is the preferred name
3435         mymiplevel = savemiplevel;
3436         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))))
3437         {
3438                 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);
3439 #ifndef USE_GLES2
3440                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3441                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3442 #endif
3443                 Mem_Free(pixels);pixels = NULL;
3444         }
3445
3446         mymiplevel = savemiplevel;
3447         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3448         {
3449                 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);
3450 #ifndef USE_GLES2
3451                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3452                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3453 #endif
3454                 Mem_Free(pixels);
3455                 pixels = NULL;
3456         }
3457
3458         mymiplevel = savemiplevel;
3459         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3460         {
3461                 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);
3462 #ifndef USE_GLES2
3463                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3464                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3465 #endif
3466                 Mem_Free(pixels);
3467                 pixels = NULL;
3468         }
3469
3470         mymiplevel = savemiplevel;
3471         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3472         {
3473                 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);
3474 #ifndef USE_GLES2
3475                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3476                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3477 #endif
3478                 Mem_Free(pixels);
3479                 pixels = NULL;
3480         }
3481
3482         mymiplevel = savemiplevel;
3483         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3484         {
3485                 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);
3486 #ifndef USE_GLES2
3487                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3488                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3489 #endif
3490                 Mem_Free(pixels);
3491                 pixels = NULL;
3492         }
3493
3494         if (basepixels)
3495                 Mem_Free(basepixels);
3496
3497         return skinframe;
3498 }
3499
3500 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3501 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3502 {
3503         int i;
3504         unsigned char *temp1, *temp2;
3505         skinframe_t *skinframe;
3506         char vabuf[1024];
3507
3508         if (cls.state == ca_dedicated)
3509                 return NULL;
3510
3511         // if already loaded just return it, otherwise make a new skinframe
3512         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3513         if (skinframe && skinframe->base)
3514                 return skinframe;
3515         textureflags &= ~TEXF_FORCE_RELOAD;
3516
3517         skinframe->stain = NULL;
3518         skinframe->merged = NULL;
3519         skinframe->base = NULL;
3520         skinframe->pants = NULL;
3521         skinframe->shirt = NULL;
3522         skinframe->nmap = NULL;
3523         skinframe->gloss = NULL;
3524         skinframe->glow = NULL;
3525         skinframe->fog = NULL;
3526         skinframe->reflect = NULL;
3527         skinframe->hasalpha = false;
3528
3529         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3530         if (!skindata)
3531                 return NULL;
3532
3533         if (developer_loading.integer)
3534                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3535
3536         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3537         {
3538                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3539                 temp2 = temp1 + width * height * 4;
3540                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3541                 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);
3542                 Mem_Free(temp1);
3543         }
3544         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3545         if (textureflags & TEXF_ALPHA)
3546         {
3547                 for (i = 3;i < width * height * 4;i += 4)
3548                 {
3549                         if (skindata[i] < 255)
3550                         {
3551                                 skinframe->hasalpha = true;
3552                                 break;
3553                         }
3554                 }
3555                 if (r_loadfog && skinframe->hasalpha)
3556                 {
3557                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3558                         memcpy(fogpixels, skindata, width * height * 4);
3559                         for (i = 0;i < width * height * 4;i += 4)
3560                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3561                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3562                         Mem_Free(fogpixels);
3563                 }
3564         }
3565
3566         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3567         //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]);
3568
3569         return skinframe;
3570 }
3571
3572 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3573 {
3574         int i;
3575         int featuresmask;
3576         skinframe_t *skinframe;
3577
3578         if (cls.state == ca_dedicated)
3579                 return NULL;
3580
3581         // if already loaded just return it, otherwise make a new skinframe
3582         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3583         if (skinframe && skinframe->base)
3584                 return skinframe;
3585         textureflags &= ~TEXF_FORCE_RELOAD;
3586
3587         skinframe->stain = NULL;
3588         skinframe->merged = NULL;
3589         skinframe->base = NULL;
3590         skinframe->pants = NULL;
3591         skinframe->shirt = NULL;
3592         skinframe->nmap = NULL;
3593         skinframe->gloss = NULL;
3594         skinframe->glow = NULL;
3595         skinframe->fog = NULL;
3596         skinframe->reflect = NULL;
3597         skinframe->hasalpha = false;
3598
3599         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3600         if (!skindata)
3601                 return NULL;
3602
3603         if (developer_loading.integer)
3604                 Con_Printf("loading quake skin \"%s\"\n", name);
3605
3606         // 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)
3607         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3608         memcpy(skinframe->qpixels, skindata, width*height);
3609         skinframe->qwidth = width;
3610         skinframe->qheight = height;
3611
3612         featuresmask = 0;
3613         for (i = 0;i < width * height;i++)
3614                 featuresmask |= palette_featureflags[skindata[i]];
3615
3616         skinframe->hasalpha = false;
3617         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3618         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3619         skinframe->qgeneratemerged = true;
3620         skinframe->qgeneratebase = skinframe->qhascolormapping;
3621         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3622
3623         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3624         //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]);
3625
3626         return skinframe;
3627 }
3628
3629 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3630 {
3631         int width;
3632         int height;
3633         unsigned char *skindata;
3634         char vabuf[1024];
3635
3636         if (!skinframe->qpixels)
3637                 return;
3638
3639         if (!skinframe->qhascolormapping)
3640                 colormapped = false;
3641
3642         if (colormapped)
3643         {
3644                 if (!skinframe->qgeneratebase)
3645                         return;
3646         }
3647         else
3648         {
3649                 if (!skinframe->qgeneratemerged)
3650                         return;
3651         }
3652
3653         width = skinframe->qwidth;
3654         height = skinframe->qheight;
3655         skindata = skinframe->qpixels;
3656
3657         if (skinframe->qgeneratenmap)
3658         {
3659                 unsigned char *temp1, *temp2;
3660                 skinframe->qgeneratenmap = false;
3661                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3662                 temp2 = temp1 + width * height * 4;
3663                 // use either a custom palette or the quake palette
3664                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3665                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3666                 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);
3667                 Mem_Free(temp1);
3668         }
3669
3670         if (skinframe->qgenerateglow)
3671         {
3672                 skinframe->qgenerateglow = false;
3673                 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
3674         }
3675
3676         if (colormapped)
3677         {
3678                 skinframe->qgeneratebase = false;
3679                 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);
3680                 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);
3681                 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);
3682         }
3683         else
3684         {
3685                 skinframe->qgeneratemerged = false;
3686                 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);
3687         }
3688
3689         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3690         {
3691                 Mem_Free(skinframe->qpixels);
3692                 skinframe->qpixels = NULL;
3693         }
3694 }
3695
3696 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)
3697 {
3698         int i;
3699         skinframe_t *skinframe;
3700         char vabuf[1024];
3701
3702         if (cls.state == ca_dedicated)
3703                 return NULL;
3704
3705         // if already loaded just return it, otherwise make a new skinframe
3706         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3707         if (skinframe && skinframe->base)
3708                 return skinframe;
3709         textureflags &= ~TEXF_FORCE_RELOAD;
3710
3711         skinframe->stain = NULL;
3712         skinframe->merged = NULL;
3713         skinframe->base = NULL;
3714         skinframe->pants = NULL;
3715         skinframe->shirt = NULL;
3716         skinframe->nmap = NULL;
3717         skinframe->gloss = NULL;
3718         skinframe->glow = NULL;
3719         skinframe->fog = NULL;
3720         skinframe->reflect = NULL;
3721         skinframe->hasalpha = false;
3722
3723         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3724         if (!skindata)
3725                 return NULL;
3726
3727         if (developer_loading.integer)
3728                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3729
3730         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3731         if (textureflags & TEXF_ALPHA)
3732         {
3733                 for (i = 0;i < width * height;i++)
3734                 {
3735                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3736                         {
3737                                 skinframe->hasalpha = true;
3738                                 break;
3739                         }
3740                 }
3741                 if (r_loadfog && skinframe->hasalpha)
3742                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3743         }
3744
3745         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3746         //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]);
3747
3748         return skinframe;
3749 }
3750
3751 skinframe_t *R_SkinFrame_LoadMissing(void)
3752 {
3753         skinframe_t *skinframe;
3754
3755         if (cls.state == ca_dedicated)
3756                 return NULL;
3757
3758         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3759         skinframe->stain = NULL;
3760         skinframe->merged = NULL;
3761         skinframe->base = NULL;
3762         skinframe->pants = NULL;
3763         skinframe->shirt = NULL;
3764         skinframe->nmap = NULL;
3765         skinframe->gloss = NULL;
3766         skinframe->glow = NULL;
3767         skinframe->fog = NULL;
3768         skinframe->reflect = NULL;
3769         skinframe->hasalpha = false;
3770
3771         skinframe->avgcolor[0] = rand() / RAND_MAX;
3772         skinframe->avgcolor[1] = rand() / RAND_MAX;
3773         skinframe->avgcolor[2] = rand() / RAND_MAX;
3774         skinframe->avgcolor[3] = 1;
3775
3776         return skinframe;
3777 }
3778
3779 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3780 typedef struct suffixinfo_s
3781 {
3782         const char *suffix;
3783         qboolean flipx, flipy, flipdiagonal;
3784 }
3785 suffixinfo_t;
3786 static suffixinfo_t suffix[3][6] =
3787 {
3788         {
3789                 {"px",   false, false, false},
3790                 {"nx",   false, false, false},
3791                 {"py",   false, false, false},
3792                 {"ny",   false, false, false},
3793                 {"pz",   false, false, false},
3794                 {"nz",   false, false, false}
3795         },
3796         {
3797                 {"posx", false, false, false},
3798                 {"negx", false, false, false},
3799                 {"posy", false, false, false},
3800                 {"negy", false, false, false},
3801                 {"posz", false, false, false},
3802                 {"negz", false, false, false}
3803         },
3804         {
3805                 {"rt",    true, false,  true},
3806                 {"lf",   false,  true,  true},
3807                 {"ft",    true,  true, false},
3808                 {"bk",   false, false, false},
3809                 {"up",    true, false,  true},
3810                 {"dn",    true, false,  true}
3811         }
3812 };
3813
3814 static int componentorder[4] = {0, 1, 2, 3};
3815
3816 static rtexture_t *R_LoadCubemap(const char *basename)
3817 {
3818         int i, j, cubemapsize;
3819         unsigned char *cubemappixels, *image_buffer;
3820         rtexture_t *cubemaptexture;
3821         char name[256];
3822         // must start 0 so the first loadimagepixels has no requested width/height
3823         cubemapsize = 0;
3824         cubemappixels = NULL;
3825         cubemaptexture = NULL;
3826         // keep trying different suffix groups (posx, px, rt) until one loads
3827         for (j = 0;j < 3 && !cubemappixels;j++)
3828         {
3829                 // load the 6 images in the suffix group
3830                 for (i = 0;i < 6;i++)
3831                 {
3832                         // generate an image name based on the base and and suffix
3833                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3834                         // load it
3835                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3836                         {
3837                                 // an image loaded, make sure width and height are equal
3838                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3839                                 {
3840                                         // if this is the first image to load successfully, allocate the cubemap memory
3841                                         if (!cubemappixels && image_width >= 1)
3842                                         {
3843                                                 cubemapsize = image_width;
3844                                                 // note this clears to black, so unavailable sides are black
3845                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3846                                         }
3847                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3848                                         if (cubemappixels)
3849                                                 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);
3850                                 }
3851                                 else
3852                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3853                                 // free the image
3854                                 Mem_Free(image_buffer);
3855                         }
3856                 }
3857         }
3858         // if a cubemap loaded, upload it
3859         if (cubemappixels)
3860         {
3861                 if (developer_loading.integer)
3862                         Con_Printf("loading cubemap \"%s\"\n", basename);
3863
3864                 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);
3865                 Mem_Free(cubemappixels);
3866         }
3867         else
3868         {
3869                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3870                 if (developer_loading.integer)
3871                 {
3872                         Con_Printf("(tried tried images ");
3873                         for (j = 0;j < 3;j++)
3874                                 for (i = 0;i < 6;i++)
3875                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3876                         Con_Print(" and was unable to find any of them).\n");
3877                 }
3878         }
3879         return cubemaptexture;
3880 }
3881
3882 rtexture_t *R_GetCubemap(const char *basename)
3883 {
3884         int i;
3885         for (i = 0;i < r_texture_numcubemaps;i++)
3886                 if (r_texture_cubemaps[i] != NULL)
3887                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3888                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3889         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3890                 return r_texture_whitecube;
3891         r_texture_numcubemaps++;
3892         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3893         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3894         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3895         return r_texture_cubemaps[i]->texture;
3896 }
3897
3898 static void R_Main_FreeViewCache(void)
3899 {
3900         if (r_refdef.viewcache.entityvisible)
3901                 Mem_Free(r_refdef.viewcache.entityvisible);
3902         if (r_refdef.viewcache.world_pvsbits)
3903                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3904         if (r_refdef.viewcache.world_leafvisible)
3905                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3906         if (r_refdef.viewcache.world_surfacevisible)
3907                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3908         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3909 }
3910
3911 static void R_Main_ResizeViewCache(void)
3912 {
3913         int numentities = r_refdef.scene.numentities;
3914         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3915         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3916         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3917         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3918         if (r_refdef.viewcache.maxentities < numentities)
3919         {
3920                 r_refdef.viewcache.maxentities = numentities;
3921                 if (r_refdef.viewcache.entityvisible)
3922                         Mem_Free(r_refdef.viewcache.entityvisible);
3923                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3924         }
3925         if (r_refdef.viewcache.world_numclusters != numclusters)
3926         {
3927                 r_refdef.viewcache.world_numclusters = numclusters;
3928                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3929                 if (r_refdef.viewcache.world_pvsbits)
3930                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3931                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3932         }
3933         if (r_refdef.viewcache.world_numleafs != numleafs)
3934         {
3935                 r_refdef.viewcache.world_numleafs = numleafs;
3936                 if (r_refdef.viewcache.world_leafvisible)
3937                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3938                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3939         }
3940         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3941         {
3942                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3943                 if (r_refdef.viewcache.world_surfacevisible)
3944                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3945                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3946         }
3947 }
3948
3949 extern rtexture_t *loadingscreentexture;
3950 static void gl_main_start(void)
3951 {
3952         loadingscreentexture = NULL;
3953         r_texture_blanknormalmap = NULL;
3954         r_texture_white = NULL;
3955         r_texture_grey128 = NULL;
3956         r_texture_black = NULL;
3957         r_texture_whitecube = NULL;
3958         r_texture_normalizationcube = NULL;
3959         r_texture_fogattenuation = NULL;
3960         r_texture_fogheighttexture = NULL;
3961         r_texture_gammaramps = NULL;
3962         r_texture_numcubemaps = 0;
3963
3964         r_loaddds = r_texture_dds_load.integer != 0;
3965         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3966
3967         switch(vid.renderpath)
3968         {
3969         case RENDERPATH_GL20:
3970         case RENDERPATH_D3D9:
3971         case RENDERPATH_D3D10:
3972         case RENDERPATH_D3D11:
3973         case RENDERPATH_SOFT:
3974         case RENDERPATH_GLES2:
3975                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3976                 Cvar_SetValueQuick(&gl_combine, 1);
3977                 Cvar_SetValueQuick(&r_glsl, 1);
3978                 r_loadnormalmap = true;
3979                 r_loadgloss = true;
3980                 r_loadfog = false;
3981                 break;
3982         case RENDERPATH_GL13:
3983         case RENDERPATH_GLES1:
3984                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3985                 Cvar_SetValueQuick(&gl_combine, 1);
3986                 Cvar_SetValueQuick(&r_glsl, 0);
3987                 r_loadnormalmap = false;
3988                 r_loadgloss = false;
3989                 r_loadfog = true;
3990                 break;
3991         case RENDERPATH_GL11:
3992                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3993                 Cvar_SetValueQuick(&gl_combine, 0);
3994                 Cvar_SetValueQuick(&r_glsl, 0);
3995                 r_loadnormalmap = false;
3996                 r_loadgloss = false;
3997                 r_loadfog = true;
3998                 break;
3999         }
4000
4001         R_AnimCache_Free();
4002         R_FrameData_Reset();
4003
4004         r_numqueries = 0;
4005         r_maxqueries = 0;
4006         memset(r_queries, 0, sizeof(r_queries));
4007
4008         r_qwskincache = NULL;
4009         r_qwskincache_size = 0;
4010
4011         // due to caching of texture_t references, the collision cache must be reset
4012         Collision_Cache_Reset(true);
4013
4014         // set up r_skinframe loading system for textures
4015         memset(&r_skinframe, 0, sizeof(r_skinframe));
4016         r_skinframe.loadsequence = 1;
4017         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4018
4019         r_main_texturepool = R_AllocTexturePool();
4020         R_BuildBlankTextures();
4021         R_BuildNoTexture();
4022         if (vid.support.arb_texture_cube_map)
4023         {
4024                 R_BuildWhiteCube();
4025                 R_BuildNormalizationCube();
4026         }
4027         r_texture_fogattenuation = NULL;
4028         r_texture_fogheighttexture = NULL;
4029         r_texture_gammaramps = NULL;
4030         //r_texture_fogintensity = NULL;
4031         memset(&r_fb, 0, sizeof(r_fb));
4032         r_glsl_permutation = NULL;
4033         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4034         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4035         glslshaderstring = NULL;
4036 #ifdef SUPPORTD3D
4037         r_hlsl_permutation = NULL;
4038         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4039         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4040 #endif
4041         hlslshaderstring = NULL;
4042         memset(&r_svbsp, 0, sizeof (r_svbsp));
4043
4044         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4045         r_texture_numcubemaps = 0;
4046
4047         r_refdef.fogmasktable_density = 0;
4048 }
4049
4050 static void gl_main_shutdown(void)
4051 {
4052         R_AnimCache_Free();
4053         R_FrameData_Reset();
4054
4055         R_Main_FreeViewCache();
4056
4057         switch(vid.renderpath)
4058         {
4059         case RENDERPATH_GL11:
4060         case RENDERPATH_GL13:
4061         case RENDERPATH_GL20:
4062         case RENDERPATH_GLES1:
4063         case RENDERPATH_GLES2:
4064 #ifdef GL_SAMPLES_PASSED_ARB
4065                 if (r_maxqueries)
4066                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4067 #endif
4068                 break;
4069         case RENDERPATH_D3D9:
4070                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4071                 break;
4072         case RENDERPATH_D3D10:
4073                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4074                 break;
4075         case RENDERPATH_D3D11:
4076                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4077                 break;
4078         case RENDERPATH_SOFT:
4079                 break;
4080         }
4081
4082         r_numqueries = 0;
4083         r_maxqueries = 0;
4084         memset(r_queries, 0, sizeof(r_queries));
4085
4086         r_qwskincache = NULL;
4087         r_qwskincache_size = 0;
4088
4089         // clear out the r_skinframe state
4090         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4091         memset(&r_skinframe, 0, sizeof(r_skinframe));
4092
4093         if (r_svbsp.nodes)
4094                 Mem_Free(r_svbsp.nodes);
4095         memset(&r_svbsp, 0, sizeof (r_svbsp));
4096         R_FreeTexturePool(&r_main_texturepool);
4097         loadingscreentexture = NULL;
4098         r_texture_blanknormalmap = NULL;
4099         r_texture_white = NULL;
4100         r_texture_grey128 = NULL;
4101         r_texture_black = NULL;
4102         r_texture_whitecube = NULL;
4103         r_texture_normalizationcube = NULL;
4104         r_texture_fogattenuation = NULL;
4105         r_texture_fogheighttexture = NULL;
4106         r_texture_gammaramps = NULL;
4107         r_texture_numcubemaps = 0;
4108         //r_texture_fogintensity = NULL;
4109         memset(&r_fb, 0, sizeof(r_fb));
4110         R_GLSL_Restart_f();
4111
4112         r_glsl_permutation = NULL;
4113         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4114         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4115         glslshaderstring = NULL;
4116 #ifdef SUPPORTD3D
4117         r_hlsl_permutation = NULL;
4118         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4119         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4120 #endif
4121         hlslshaderstring = NULL;
4122 }
4123
4124 static void gl_main_newmap(void)
4125 {
4126         // FIXME: move this code to client
4127         char *entities, entname[MAX_QPATH];
4128         if (r_qwskincache)
4129                 Mem_Free(r_qwskincache);
4130         r_qwskincache = NULL;
4131         r_qwskincache_size = 0;
4132         if (cl.worldmodel)
4133         {
4134                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4135                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4136                 {
4137                         CL_ParseEntityLump(entities);
4138                         Mem_Free(entities);
4139                         return;
4140                 }
4141                 if (cl.worldmodel->brush.entities)
4142                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4143         }
4144         R_Main_FreeViewCache();
4145
4146         R_FrameData_Reset();
4147 }
4148
4149 void GL_Main_Init(void)
4150 {
4151         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4152
4153         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4154         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4155         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4156         if (gamemode == GAME_NEHAHRA)
4157         {
4158                 Cvar_RegisterVariable (&gl_fogenable);
4159                 Cvar_RegisterVariable (&gl_fogdensity);
4160                 Cvar_RegisterVariable (&gl_fogred);
4161                 Cvar_RegisterVariable (&gl_foggreen);
4162                 Cvar_RegisterVariable (&gl_fogblue);
4163                 Cvar_RegisterVariable (&gl_fogstart);
4164                 Cvar_RegisterVariable (&gl_fogend);
4165                 Cvar_RegisterVariable (&gl_skyclip);
4166         }
4167         Cvar_RegisterVariable(&r_motionblur);
4168         Cvar_RegisterVariable(&r_damageblur);
4169         Cvar_RegisterVariable(&r_motionblur_averaging);
4170         Cvar_RegisterVariable(&r_motionblur_randomize);
4171         Cvar_RegisterVariable(&r_motionblur_minblur);
4172         Cvar_RegisterVariable(&r_motionblur_maxblur);
4173         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4174         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4176         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4177         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4179         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4180         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4181         Cvar_RegisterVariable(&r_equalize_entities_by);
4182         Cvar_RegisterVariable(&r_equalize_entities_to);
4183         Cvar_RegisterVariable(&r_depthfirst);
4184         Cvar_RegisterVariable(&r_useinfinitefarclip);
4185         Cvar_RegisterVariable(&r_farclip_base);
4186         Cvar_RegisterVariable(&r_farclip_world);
4187         Cvar_RegisterVariable(&r_nearclip);
4188         Cvar_RegisterVariable(&r_deformvertexes);
4189         Cvar_RegisterVariable(&r_transparent);
4190         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4191         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4192         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4193         Cvar_RegisterVariable(&r_showoverdraw);
4194         Cvar_RegisterVariable(&r_showbboxes);
4195         Cvar_RegisterVariable(&r_showsurfaces);
4196         Cvar_RegisterVariable(&r_showtris);
4197         Cvar_RegisterVariable(&r_shownormals);
4198         Cvar_RegisterVariable(&r_showlighting);
4199         Cvar_RegisterVariable(&r_showshadowvolumes);
4200         Cvar_RegisterVariable(&r_showcollisionbrushes);
4201         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4203         Cvar_RegisterVariable(&r_showdisabledepthtest);
4204         Cvar_RegisterVariable(&r_drawportals);
4205         Cvar_RegisterVariable(&r_drawentities);
4206         Cvar_RegisterVariable(&r_draw2d);
4207         Cvar_RegisterVariable(&r_drawworld);
4208         Cvar_RegisterVariable(&r_cullentities_trace);
4209         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4210         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4211         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4212         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4213         Cvar_RegisterVariable(&r_sortentities);
4214         Cvar_RegisterVariable(&r_drawviewmodel);
4215         Cvar_RegisterVariable(&r_drawexteriormodel);
4216         Cvar_RegisterVariable(&r_speeds);
4217         Cvar_RegisterVariable(&r_fullbrights);
4218         Cvar_RegisterVariable(&r_wateralpha);
4219         Cvar_RegisterVariable(&r_dynamic);
4220         Cvar_RegisterVariable(&r_fakelight);
4221         Cvar_RegisterVariable(&r_fakelight_intensity);
4222         Cvar_RegisterVariable(&r_fullbright);
4223         Cvar_RegisterVariable(&r_shadows);
4224         Cvar_RegisterVariable(&r_shadows_darken);
4225         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4226         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4227         Cvar_RegisterVariable(&r_shadows_throwdistance);
4228         Cvar_RegisterVariable(&r_shadows_throwdirection);
4229         Cvar_RegisterVariable(&r_shadows_focus);
4230         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4231         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4232         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4233         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4234         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4235         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4236         Cvar_RegisterVariable(&r_fog_exp2);
4237         Cvar_RegisterVariable(&r_fog_clear);
4238         Cvar_RegisterVariable(&r_drawfog);
4239         Cvar_RegisterVariable(&r_transparentdepthmasking);
4240         Cvar_RegisterVariable(&r_transparent_sortmindist);
4241         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4242         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4243         Cvar_RegisterVariable(&r_texture_dds_load);
4244         Cvar_RegisterVariable(&r_texture_dds_save);
4245         Cvar_RegisterVariable(&r_textureunits);
4246         Cvar_RegisterVariable(&gl_combine);
4247         Cvar_RegisterVariable(&r_usedepthtextures);
4248         Cvar_RegisterVariable(&r_viewfbo);
4249         Cvar_RegisterVariable(&r_viewscale);
4250         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4256         Cvar_RegisterVariable(&r_glsl);
4257         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4266         Cvar_RegisterVariable(&r_glsl_postprocess);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4275
4276         Cvar_RegisterVariable(&r_water);
4277         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4278         Cvar_RegisterVariable(&r_water_clippingplanebias);
4279         Cvar_RegisterVariable(&r_water_refractdistort);
4280         Cvar_RegisterVariable(&r_water_reflectdistort);
4281         Cvar_RegisterVariable(&r_water_scissormode);
4282         Cvar_RegisterVariable(&r_water_lowquality);
4283         Cvar_RegisterVariable(&r_water_hideplayer);
4284         Cvar_RegisterVariable(&r_water_fbo);
4285
4286         Cvar_RegisterVariable(&r_lerpsprites);
4287         Cvar_RegisterVariable(&r_lerpmodels);
4288         Cvar_RegisterVariable(&r_lerplightstyles);
4289         Cvar_RegisterVariable(&r_waterscroll);
4290         Cvar_RegisterVariable(&r_bloom);
4291         Cvar_RegisterVariable(&r_bloom_colorscale);
4292         Cvar_RegisterVariable(&r_bloom_brighten);
4293         Cvar_RegisterVariable(&r_bloom_blur);
4294         Cvar_RegisterVariable(&r_bloom_resolution);
4295         Cvar_RegisterVariable(&r_bloom_colorexponent);
4296         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4297         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4298         Cvar_RegisterVariable(&r_hdr_glowintensity);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4300         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4307         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4308         Cvar_RegisterVariable(&developer_texturelogging);
4309         Cvar_RegisterVariable(&gl_lightmaps);
4310         Cvar_RegisterVariable(&r_test);
4311         Cvar_RegisterVariable(&r_glsl_saturation);
4312         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4313         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4314         Cvar_RegisterVariable(&r_framedatasize);
4315         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4316                 Cvar_SetValue("r_fullbrights", 0);
4317         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4318 }
4319
4320 void Render_Init(void)
4321 {
4322         gl_backend_init();
4323         R_Textures_Init();
4324         GL_Main_Init();
4325         Font_Init();
4326         GL_Draw_Init();
4327         R_Shadow_Init();
4328         R_Sky_Init();
4329         GL_Surf_Init();
4330         Sbar_Init();
4331         R_Particles_Init();
4332         R_Explosion_Init();
4333         R_LightningBeams_Init();
4334         Mod_RenderInit();
4335 }
4336
4337 /*
4338 ===============
4339 GL_Init
4340 ===============
4341 */
4342 #ifndef USE_GLES2
4343 extern char *ENGINE_EXTENSIONS;
4344 void GL_Init (void)
4345 {
4346         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4347         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4348         gl_version = (const char *)qglGetString(GL_VERSION);
4349         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4350
4351         if (!gl_extensions)
4352                 gl_extensions = "";
4353         if (!gl_platformextensions)
4354                 gl_platformextensions = "";
4355
4356         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4357         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4358         Con_Printf("GL_VERSION: %s\n", gl_version);
4359         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4360         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4361
4362         VID_CheckExtensions();
4363
4364         // LordHavoc: report supported extensions
4365         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4366
4367         // clear to black (loading plaque will be seen over this)
4368         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4369 }
4370 #endif
4371
4372 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4373 {
4374         int i;
4375         mplane_t *p;
4376         if (r_trippy.integer)
4377                 return false;
4378         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4379         {
4380                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4381                 if (i == 4)
4382                         continue;
4383                 p = r_refdef.view.frustum + i;
4384                 switch(p->signbits)
4385                 {
4386                 default:
4387                 case 0:
4388                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 1:
4392                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 case 2:
4396                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 3:
4400                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 4:
4404                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 5:
4408                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 6:
4412                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 7:
4416                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 }
4420         }
4421         return false;
4422 }
4423
4424 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4425 {
4426         int i;
4427         const mplane_t *p;
4428         if (r_trippy.integer)
4429                 return false;
4430         for (i = 0;i < numplanes;i++)
4431         {
4432                 p = planes + i;
4433                 switch(p->signbits)
4434                 {
4435                 default:
4436                 case 0:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 1:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 2:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 3:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 4:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 5:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 6:
4461                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 7:
4465                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 }
4469         }
4470         return false;
4471 }
4472
4473 //==================================================================================
4474
4475 // LordHavoc: this stores temporary data used within the same frame
4476
4477 typedef struct r_framedata_mem_s
4478 {
4479         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4480         size_t size; // how much usable space
4481         size_t current; // how much space in use
4482         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4483         size_t wantedsize; // how much space was allocated
4484         unsigned char *data; // start of real data (16byte aligned)
4485 }
4486 r_framedata_mem_t;
4487
4488 static r_framedata_mem_t *r_framedata_mem;
4489
4490 void R_FrameData_Reset(void)
4491 {
4492         while (r_framedata_mem)
4493         {
4494                 r_framedata_mem_t *next = r_framedata_mem->purge;
4495                 Mem_Free(r_framedata_mem);
4496                 r_framedata_mem = next;
4497         }
4498 }
4499
4500 static void R_FrameData_Resize(void)
4501 {
4502         size_t wantedsize;
4503         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4504         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4505         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4506         {
4507                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4508                 newmem->wantedsize = wantedsize;
4509                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4510                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4511                 newmem->current = 0;
4512                 newmem->mark = 0;
4513                 newmem->purge = r_framedata_mem;
4514                 r_framedata_mem = newmem;
4515         }
4516 }
4517
4518 void R_FrameData_NewFrame(void)
4519 {
4520         R_FrameData_Resize();
4521         if (!r_framedata_mem)
4522                 return;
4523         // if we ran out of space on the last frame, free the old memory now
4524         while (r_framedata_mem->purge)
4525         {
4526                 // repeatedly remove the second item in the list, leaving only head
4527                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4528                 Mem_Free(r_framedata_mem->purge);
4529                 r_framedata_mem->purge = next;
4530         }
4531         // reset the current mem pointer
4532         r_framedata_mem->current = 0;
4533         r_framedata_mem->mark = 0;
4534 }
4535
4536 void *R_FrameData_Alloc(size_t size)
4537 {
4538         void *data;
4539
4540         // align to 16 byte boundary - the data pointer is already aligned, so we
4541         // only need to ensure the size of every allocation is also aligned
4542         size = (size + 15) & ~15;
4543
4544         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4545         {
4546                 // emergency - we ran out of space, allocate more memory
4547                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4548                 R_FrameData_Resize();
4549         }
4550
4551         data = r_framedata_mem->data + r_framedata_mem->current;
4552         r_framedata_mem->current += size;
4553
4554         // count the usage for stats
4555         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4556         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4557
4558         return (void *)data;
4559 }
4560
4561 void *R_FrameData_Store(size_t size, void *data)
4562 {
4563         void *d = R_FrameData_Alloc(size);
4564         if (d && data)
4565                 memcpy(d, data, size);
4566         return d;
4567 }
4568
4569 void R_FrameData_SetMark(void)
4570 {
4571         if (!r_framedata_mem)
4572                 return;
4573         r_framedata_mem->mark = r_framedata_mem->current;
4574 }
4575
4576 void R_FrameData_ReturnToMark(void)
4577 {
4578         if (!r_framedata_mem)
4579                 return;
4580         r_framedata_mem->current = r_framedata_mem->mark;
4581 }
4582
4583 //==================================================================================
4584
4585 // LordHavoc: animcache originally written by Echon, rewritten since then
4586
4587 /**
4588  * Animation cache prevents re-generating mesh data for an animated model
4589  * multiple times in one frame for lighting, shadowing, reflections, etc.
4590  */
4591
4592 void R_AnimCache_Free(void)
4593 {
4594 }
4595
4596 void R_AnimCache_ClearCache(void)
4597 {
4598         int i;
4599         entity_render_t *ent;
4600
4601         for (i = 0;i < r_refdef.scene.numentities;i++)
4602         {
4603                 ent = r_refdef.scene.entities[i];
4604                 ent->animcache_vertex3f = NULL;
4605                 ent->animcache_normal3f = NULL;
4606                 ent->animcache_svector3f = NULL;
4607                 ent->animcache_tvector3f = NULL;
4608                 ent->animcache_vertexmesh = NULL;
4609                 ent->animcache_vertex3fbuffer = NULL;
4610                 ent->animcache_vertexmeshbuffer = NULL;
4611         }
4612 }
4613
4614 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4615 {
4616         int i;
4617
4618         // check if we need the meshbuffers
4619         if (!vid.useinterleavedarrays)
4620                 return;
4621
4622         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4623                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4624         // TODO: upload vertex3f buffer?
4625         if (ent->animcache_vertexmesh)
4626         {
4627                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4628                 for (i = 0;i < numvertices;i++)
4629                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4630                 if (ent->animcache_svector3f)
4631                         for (i = 0;i < numvertices;i++)
4632                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4633                 if (ent->animcache_tvector3f)
4634                         for (i = 0;i < numvertices;i++)
4635                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4636                 if (ent->animcache_normal3f)
4637                         for (i = 0;i < numvertices;i++)
4638                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4639                 // TODO: upload vertexmeshbuffer?
4640         }
4641 }
4642
4643 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4644 {
4645         dp_model_t *model = ent->model;
4646         int numvertices;
4647         // see if it's already cached this frame
4648         if (ent->animcache_vertex3f)
4649         {
4650                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4651                 if (wantnormals || wanttangents)
4652                 {
4653                         if (ent->animcache_normal3f)
4654                                 wantnormals = false;
4655                         if (ent->animcache_svector3f)
4656                                 wanttangents = false;
4657                         if (wantnormals || wanttangents)
4658                         {
4659                                 numvertices = model->surfmesh.num_vertices;
4660                                 if (wantnormals)
4661                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4662                                 if (wanttangents)
4663                                 {
4664                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4666                                 }
4667                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4668                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4669                         }
4670                 }
4671         }
4672         else
4673         {
4674                 // see if this ent is worth caching
4675                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4676                         return false;
4677                 // get some memory for this entity and generate mesh data
4678                 numvertices = model->surfmesh.num_vertices;
4679                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4680                 if (wantnormals)
4681                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4682                 if (wanttangents)
4683                 {
4684                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4686                 }
4687                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4688                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4689         }
4690         return true;
4691 }
4692
4693 void R_AnimCache_CacheVisibleEntities(void)
4694 {
4695         int i;
4696         qboolean wantnormals = true;
4697         qboolean wanttangents = !r_showsurfaces.integer;
4698
4699         switch(vid.renderpath)
4700         {
4701         case RENDERPATH_GL20:
4702         case RENDERPATH_D3D9:
4703         case RENDERPATH_D3D10:
4704         case RENDERPATH_D3D11:
4705         case RENDERPATH_GLES2:
4706                 break;
4707         case RENDERPATH_GL11:
4708         case RENDERPATH_GL13:
4709         case RENDERPATH_GLES1:
4710                 wanttangents = false;
4711                 break;
4712         case RENDERPATH_SOFT:
4713                 break;
4714         }
4715
4716         if (r_shownormals.integer)
4717                 wanttangents = wantnormals = true;
4718
4719         // TODO: thread this
4720         // NOTE: R_PrepareRTLights() also caches entities
4721
4722         for (i = 0;i < r_refdef.scene.numentities;i++)
4723                 if (r_refdef.viewcache.entityvisible[i])
4724                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4725 }
4726
4727 //==================================================================================
4728
4729 extern cvar_t r_overheadsprites_pushback;
4730
4731 static void R_View_UpdateEntityLighting (void)
4732 {
4733         int i;
4734         entity_render_t *ent;
4735         vec3_t tempdiffusenormal, avg;
4736         vec_t f, fa, fd, fdd;
4737         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4738
4739         for (i = 0;i < r_refdef.scene.numentities;i++)
4740         {
4741                 ent = r_refdef.scene.entities[i];
4742
4743                 // skip unseen models and models that updated by CSQC
4744                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4745                         continue;
4746
4747                 // skip bsp models
4748                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4749                 {
4750                         // TODO: use modellight for r_ambient settings on world?
4751                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4752                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4753                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4754                         continue;
4755                 }
4756
4757                 // fetch the lighting from the worldmodel data
4758                 VectorClear(ent->modellight_ambient);
4759                 VectorClear(ent->modellight_diffuse);
4760                 VectorClear(tempdiffusenormal);
4761                 if (ent->flags & RENDER_LIGHT)
4762                 {
4763                         vec3_t org;
4764                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4765
4766                         // complete lightning for lit sprites
4767                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4768                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4769                         {
4770                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4771                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4772                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4773                         }
4774                         else
4775                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4776
4777                         if(ent->flags & RENDER_EQUALIZE)
4778                         {
4779                                 // first fix up ambient lighting...
4780                                 if(r_equalize_entities_minambient.value > 0)
4781                                 {
4782                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4783                                         if(fd > 0)
4784                                         {
4785                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4786                                                 if(fa < r_equalize_entities_minambient.value * fd)
4787                                                 {
4788                                                         // solve:
4789                                                         //   fa'/fd' = minambient
4790                                                         //   fa'+0.25*fd' = fa+0.25*fd
4791                                                         //   ...
4792                                                         //   fa' = fd' * minambient
4793                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4794                                                         //   ...
4795                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4796                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4797                                                         //   ...
4798                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4799                                                         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
4800                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4801                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4802                                                 }
4803                                         }
4804                                 }
4805
4806                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4807                                 {
4808                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4809                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4810                                         f = fa + 0.25 * fd;
4811                                         if(f > 0)
4812                                         {
4813                                                 // adjust brightness and saturation to target
4814                                                 avg[0] = avg[1] = avg[2] = fa / f;
4815                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4816                                                 avg[0] = avg[1] = avg[2] = fd / f;
4817                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4818                                         }
4819                                 }
4820                         }
4821                 }
4822                 else // highly rare
4823                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4824
4825                 // move the light direction into modelspace coordinates for lighting code
4826                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4827                 if(VectorLength2(ent->modellight_lightdir) == 0)
4828                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4829                 VectorNormalize(ent->modellight_lightdir);
4830         }
4831 }
4832
4833 #define MAX_LINEOFSIGHTTRACES 64
4834
4835 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4836 {
4837         int i;
4838         vec3_t boxmins, boxmaxs;
4839         vec3_t start;
4840         vec3_t end;
4841         dp_model_t *model = r_refdef.scene.worldmodel;
4842
4843         if (!model || !model->brush.TraceLineOfSight)
4844                 return true;
4845
4846         // expand the box a little
4847         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4848         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4849         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4850         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4851         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4852         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4853
4854         // return true if eye is inside enlarged box
4855         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4856                 return true;
4857
4858         // try center
4859         VectorCopy(eye, start);
4860         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4861         if (model->brush.TraceLineOfSight(model, start, end))
4862                 return true;
4863
4864         // try various random positions
4865         for (i = 0;i < numsamples;i++)
4866         {
4867                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4868                 if (model->brush.TraceLineOfSight(model, start, end))
4869                         return true;
4870         }
4871
4872         return false;
4873 }
4874
4875
4876 static void R_View_UpdateEntityVisible (void)
4877 {
4878         int i;
4879         int renderimask;
4880         int samples;
4881         entity_render_t *ent;
4882
4883         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4884                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4885                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4886                 :                                                          RENDER_EXTERIORMODEL;
4887         if (!r_drawviewmodel.integer)
4888                 renderimask |= RENDER_VIEWMODEL;
4889         if (!r_drawexteriormodel.integer)
4890                 renderimask |= RENDER_EXTERIORMODEL;
4891         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4892         {
4893                 // worldmodel can check visibility
4894                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4895                 for (i = 0;i < r_refdef.scene.numentities;i++)
4896                 {
4897                         ent = r_refdef.scene.entities[i];
4898                         if (!(ent->flags & renderimask))
4899                         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)))
4900                         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))
4901                                 r_refdef.viewcache.entityvisible[i] = true;
4902                 }
4903         }
4904         else
4905         {
4906                 // no worldmodel or it can't check visibility
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         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));
4911                 }
4912         }
4913         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4914                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4915         {
4916                 for (i = 0;i < r_refdef.scene.numentities;i++)
4917                 {
4918                         if (!r_refdef.viewcache.entityvisible[i])
4919                                 continue;
4920                         ent = r_refdef.scene.entities[i];
4921                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4922                         {
4923                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4924                                 if (samples < 0)
4925                                         continue; // temp entities do pvs only
4926                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4927                                         ent->last_trace_visibility = realtime;
4928                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4929                                         r_refdef.viewcache.entityvisible[i] = 0;
4930                         }
4931                 }
4932         }
4933 }
4934
4935 /// only used if skyrendermasked, and normally returns false
4936 static int R_DrawBrushModelsSky (void)
4937 {
4938         int i, sky;
4939         entity_render_t *ent;
4940
4941         sky = false;
4942         for (i = 0;i < r_refdef.scene.numentities;i++)
4943         {
4944                 if (!r_refdef.viewcache.entityvisible[i])
4945                         continue;
4946                 ent = r_refdef.scene.entities[i];
4947                 if (!ent->model || !ent->model->DrawSky)
4948                         continue;
4949                 ent->model->DrawSky(ent);
4950                 sky = true;
4951         }
4952         return sky;
4953 }
4954
4955 static void R_DrawNoModel(entity_render_t *ent);
4956 static void R_DrawModels(void)
4957 {
4958         int i;
4959         entity_render_t *ent;
4960
4961         for (i = 0;i < r_refdef.scene.numentities;i++)
4962         {
4963                 if (!r_refdef.viewcache.entityvisible[i])
4964                         continue;
4965                 ent = r_refdef.scene.entities[i];
4966                 r_refdef.stats.entities++;
4967                 /*
4968                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4969                 {
4970                         vec3_t f, l, u, o;
4971                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4972                         Con_Printf("R_DrawModels\n");
4973                         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]);
4974                         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);
4975                         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);
4976                 }
4977                 */
4978                 if (ent->model && ent->model->Draw != NULL)
4979                         ent->model->Draw(ent);
4980                 else
4981                         R_DrawNoModel(ent);
4982         }
4983 }
4984
4985 static void R_DrawModelsDepth(void)
4986 {
4987         int i;
4988         entity_render_t *ent;
4989
4990         for (i = 0;i < r_refdef.scene.numentities;i++)
4991         {
4992                 if (!r_refdef.viewcache.entityvisible[i])
4993                         continue;
4994                 ent = r_refdef.scene.entities[i];
4995                 if (ent->model && ent->model->DrawDepth != NULL)
4996                         ent->model->DrawDepth(ent);
4997         }
4998 }
4999
5000 static void R_DrawModelsDebug(void)
5001 {
5002         int i;
5003         entity_render_t *ent;
5004
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (ent->model && ent->model->DrawDebug != NULL)
5011                         ent->model->DrawDebug(ent);
5012         }
5013 }
5014
5015 static void R_DrawModelsAddWaterPlanes(void)
5016 {
5017         int i;
5018         entity_render_t *ent;
5019
5020         for (i = 0;i < r_refdef.scene.numentities;i++)
5021         {
5022                 if (!r_refdef.viewcache.entityvisible[i])
5023                         continue;
5024                 ent = r_refdef.scene.entities[i];
5025                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5026                         ent->model->DrawAddWaterPlanes(ent);
5027         }
5028 }
5029
5030 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}};
5031
5032 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5033 {
5034         if (r_hdr_irisadaptation.integer)
5035         {
5036                 vec3_t p;
5037                 vec3_t ambient;
5038                 vec3_t diffuse;
5039                 vec3_t diffusenormal;
5040                 vec3_t forward;
5041                 vec_t brightness = 0.0f;
5042                 vec_t goal;
5043                 vec_t current;
5044                 vec_t d;
5045                 int c;
5046                 VectorCopy(r_refdef.view.forward, forward);
5047                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5048                 {
5049                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5050                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5051                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5052                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5053                         d = DotProduct(forward, diffusenormal);
5054                         brightness += VectorLength(ambient);
5055                         if (d > 0)
5056                                 brightness += d * VectorLength(diffuse);
5057                 }
5058                 brightness *= 1.0f / c;
5059                 brightness += 0.00001f; // make sure it's never zero
5060                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5061                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5062                 current = r_hdr_irisadaptation_value.value;
5063                 if (current < goal)
5064                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5065                 else if (current > goal)
5066                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5067                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5068                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5069         }
5070         else if (r_hdr_irisadaptation_value.value != 1.0f)
5071                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5072 }
5073
5074 static void R_View_SetFrustum(const int *scissor)
5075 {
5076         int i;
5077         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5078         vec3_t forward, left, up, origin, v;
5079
5080         if(scissor)
5081         {
5082                 // flipped x coordinates (because x points left here)
5083                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5084                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5085
5086                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5087                 switch(vid.renderpath)
5088                 {
5089                         case RENDERPATH_D3D9:
5090                         case RENDERPATH_D3D10:
5091                         case RENDERPATH_D3D11:
5092                                 // non-flipped y coordinates
5093                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5094                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5095                                 break;
5096                         case RENDERPATH_SOFT:
5097                         case RENDERPATH_GL11:
5098                         case RENDERPATH_GL13:
5099                         case RENDERPATH_GL20:
5100                         case RENDERPATH_GLES1:
5101                         case RENDERPATH_GLES2:
5102                                 // non-flipped y coordinates
5103                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5104                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105                                 break;
5106                 }
5107         }
5108
5109         // we can't trust r_refdef.view.forward and friends in reflected scenes
5110         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5111
5112 #if 0
5113         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5114         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5115         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5116         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5117         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5118         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5119         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5120         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5121         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5122         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5123         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5124         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5125 #endif
5126
5127 #if 0
5128         zNear = r_refdef.nearclip;
5129         nudge = 1.0 - 1.0 / (1<<23);
5130         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5131         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5132         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5133         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5134         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5136         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5137         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5138 #endif
5139
5140
5141
5142 #if 0
5143         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5144         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5145         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5146         r_refdef.view.frustum[0].dist = m[15] - m[12];
5147
5148         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5149         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5150         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5151         r_refdef.view.frustum[1].dist = m[15] + m[12];
5152
5153         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5154         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5155         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5156         r_refdef.view.frustum[2].dist = m[15] - m[13];
5157
5158         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5159         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5160         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5161         r_refdef.view.frustum[3].dist = m[15] + m[13];
5162
5163         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5164         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5165         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5166         r_refdef.view.frustum[4].dist = m[15] - m[14];
5167
5168         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5169         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5170         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5171         r_refdef.view.frustum[5].dist = m[15] + m[14];
5172 #endif
5173
5174         if (r_refdef.view.useperspective)
5175         {
5176                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5177                 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]);
5178                 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]);
5179                 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]);
5180                 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]);
5181
5182                 // then the normals from the corners relative to origin
5183                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5184                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5185                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5186                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5187
5188                 // in a NORMAL view, forward cross left == up
5189                 // in a REFLECTED view, forward cross left == down
5190                 // so our cross products above need to be adjusted for a left handed coordinate system
5191                 CrossProduct(forward, left, v);
5192                 if(DotProduct(v, up) < 0)
5193                 {
5194                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5195                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5196                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5197                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5198                 }
5199
5200                 // Leaving those out was a mistake, those were in the old code, and they
5201                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5202                 // I couldn't reproduce it after adding those normalizations. --blub
5203                 VectorNormalize(r_refdef.view.frustum[0].normal);
5204                 VectorNormalize(r_refdef.view.frustum[1].normal);
5205                 VectorNormalize(r_refdef.view.frustum[2].normal);
5206                 VectorNormalize(r_refdef.view.frustum[3].normal);
5207
5208                 // make the corners absolute
5209                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5210                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5211                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5212                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5213
5214                 // one more normal
5215                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5216
5217                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5218                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5219                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5220                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5221                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5222         }
5223         else
5224         {
5225                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5226                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5227                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5228                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5229                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5230                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5231                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5232                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5233                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5234                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5235         }
5236         r_refdef.view.numfrustumplanes = 5;
5237
5238         if (r_refdef.view.useclipplane)
5239         {
5240                 r_refdef.view.numfrustumplanes = 6;
5241                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5242         }
5243
5244         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5245                 PlaneClassify(r_refdef.view.frustum + i);
5246
5247         // LordHavoc: note to all quake engine coders, Quake had a special case
5248         // for 90 degrees which assumed a square view (wrong), so I removed it,
5249         // Quake2 has it disabled as well.
5250
5251         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5252         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5253         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5254         //PlaneClassify(&frustum[0]);
5255
5256         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5257         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5258         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5259         //PlaneClassify(&frustum[1]);
5260
5261         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5262         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5263         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5264         //PlaneClassify(&frustum[2]);
5265
5266         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5267         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5268         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5269         //PlaneClassify(&frustum[3]);
5270
5271         // nearclip plane
5272         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5273         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5274         //PlaneClassify(&frustum[4]);
5275 }
5276
5277 static void R_View_UpdateWithScissor(const int *myscissor)
5278 {
5279         R_Main_ResizeViewCache();
5280         R_View_SetFrustum(myscissor);
5281         R_View_WorldVisibility(r_refdef.view.useclipplane);
5282         R_View_UpdateEntityVisible();
5283         R_View_UpdateEntityLighting();
5284         R_AnimCache_CacheVisibleEntities();
5285 }
5286
5287 static void R_View_Update(void)
5288 {
5289         R_Main_ResizeViewCache();
5290         R_View_SetFrustum(NULL);
5291         R_View_WorldVisibility(r_refdef.view.useclipplane);
5292         R_View_UpdateEntityVisible();
5293         R_View_UpdateEntityLighting();
5294         R_AnimCache_CacheVisibleEntities();
5295 }
5296
5297 float viewscalefpsadjusted = 1.0f;
5298
5299 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5300 {
5301         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5302         scale = bound(0.03125f, scale, 1.0f);
5303         *outwidth = (int)ceil(width * scale);
5304         *outheight = (int)ceil(height * scale);
5305 }
5306
5307 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5308 {
5309         const float *customclipplane = NULL;
5310         float plane[4];
5311         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5312         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5313         {
5314                 // LordHavoc: couldn't figure out how to make this approach the
5315                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5316                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5317                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5318                         dist = r_refdef.view.clipplane.dist;
5319                 plane[0] = r_refdef.view.clipplane.normal[0];
5320                 plane[1] = r_refdef.view.clipplane.normal[1];
5321                 plane[2] = r_refdef.view.clipplane.normal[2];
5322                 plane[3] = -dist;
5323                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5324         }
5325
5326         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5327         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5328
5329         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5330         if (!r_refdef.view.useperspective)
5331                 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);
5332         else if (vid.stencil && r_useinfinitefarclip.integer)
5333                 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);
5334         else
5335                 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);
5336         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5337         R_SetViewport(&r_refdef.view.viewport);
5338         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5339         {
5340                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5341                 float screenplane[4];
5342                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5343                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5344                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5345                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5346                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5347         }
5348 }
5349
5350 void R_EntityMatrix(const matrix4x4_t *matrix)
5351 {
5352         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5353         {
5354                 gl_modelmatrixchanged = false;
5355                 gl_modelmatrix = *matrix;
5356                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5357                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5358                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5359                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5360                 CHECKGLERROR
5361                 switch(vid.renderpath)
5362                 {
5363                 case RENDERPATH_D3D9:
5364 #ifdef SUPPORTD3D
5365                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5366                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5367 #endif
5368                         break;
5369                 case RENDERPATH_D3D10:
5370                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5371                         break;
5372                 case RENDERPATH_D3D11:
5373                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5374                         break;
5375                 case RENDERPATH_GL11:
5376                 case RENDERPATH_GL13:
5377                 case RENDERPATH_GLES1:
5378                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5379                         break;
5380                 case RENDERPATH_SOFT:
5381                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5382                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5383                         break;
5384                 case RENDERPATH_GL20:
5385                 case RENDERPATH_GLES2:
5386                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5387                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5388                         break;
5389                 }
5390         }
5391 }
5392
5393 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5394 {
5395         r_viewport_t viewport;
5396
5397         CHECKGLERROR
5398
5399         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5400         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);
5401         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5402         R_SetViewport(&viewport);
5403         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5404         GL_Color(1, 1, 1, 1);
5405         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5406         GL_BlendFunc(GL_ONE, GL_ZERO);
5407         GL_ScissorTest(false);
5408         GL_DepthMask(false);
5409         GL_DepthRange(0, 1);
5410         GL_DepthTest(false);
5411         GL_DepthFunc(GL_LEQUAL);
5412         R_EntityMatrix(&identitymatrix);
5413         R_Mesh_ResetTextureState();
5414         GL_PolygonOffset(0, 0);
5415         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5416         switch(vid.renderpath)
5417         {
5418         case RENDERPATH_GL11:
5419         case RENDERPATH_GL13:
5420         case RENDERPATH_GL20:
5421         case RENDERPATH_GLES1:
5422         case RENDERPATH_GLES2:
5423                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5424                 break;
5425         case RENDERPATH_D3D9:
5426         case RENDERPATH_D3D10:
5427         case RENDERPATH_D3D11:
5428         case RENDERPATH_SOFT:
5429                 break;
5430         }
5431         GL_CullFace(GL_NONE);
5432
5433         CHECKGLERROR
5434 }
5435
5436 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5437 {
5438         DrawQ_Finish();
5439
5440         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5441 }
5442
5443 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5444 {
5445         DrawQ_Finish();
5446
5447         R_SetupView(true, fbo, depthtexture, colortexture);
5448         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5449         GL_Color(1, 1, 1, 1);
5450         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5451         GL_BlendFunc(GL_ONE, GL_ZERO);
5452         GL_ScissorTest(true);
5453         GL_DepthMask(true);
5454         GL_DepthRange(0, 1);
5455         GL_DepthTest(true);
5456         GL_DepthFunc(GL_LEQUAL);
5457         R_EntityMatrix(&identitymatrix);
5458         R_Mesh_ResetTextureState();
5459         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5460         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5461         switch(vid.renderpath)
5462         {
5463         case RENDERPATH_GL11:
5464         case RENDERPATH_GL13:
5465         case RENDERPATH_GL20:
5466         case RENDERPATH_GLES1:
5467         case RENDERPATH_GLES2:
5468                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5469                 break;
5470         case RENDERPATH_D3D9:
5471         case RENDERPATH_D3D10:
5472         case RENDERPATH_D3D11:
5473         case RENDERPATH_SOFT:
5474                 break;
5475         }
5476         GL_CullFace(r_refdef.view.cullface_back);
5477 }
5478
5479 /*
5480 ================
5481 R_RenderView_UpdateViewVectors
5482 ================
5483 */
5484 void R_RenderView_UpdateViewVectors(void)
5485 {
5486         // break apart the view matrix into vectors for various purposes
5487         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5488         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5489         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5490         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5491         // make an inverted copy of the view matrix for tracking sprites
5492         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5493 }
5494
5495 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5496 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5497
5498 static void R_Water_StartFrame(void)
5499 {
5500         int i;
5501         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5502         r_waterstate_waterplane_t *p;
5503         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5504
5505         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5506                 return;
5507
5508         switch(vid.renderpath)
5509         {
5510         case RENDERPATH_GL20:
5511         case RENDERPATH_D3D9:
5512         case RENDERPATH_D3D10:
5513         case RENDERPATH_D3D11:
5514         case RENDERPATH_SOFT:
5515         case RENDERPATH_GLES2:
5516                 break;
5517         case RENDERPATH_GL11:
5518         case RENDERPATH_GL13:
5519         case RENDERPATH_GLES1:
5520                 return;
5521         }
5522
5523         // set waterwidth and waterheight to the water resolution that will be
5524         // used (often less than the screen resolution for faster rendering)
5525         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5526
5527         // calculate desired texture sizes
5528         // can't use water if the card does not support the texture size
5529         if (!r_water.integer || r_showsurfaces.integer)
5530                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5531         else if (vid.support.arb_texture_non_power_of_two)
5532         {
5533                 texturewidth = waterwidth;
5534                 textureheight = waterheight;
5535                 camerawidth = waterwidth;
5536                 cameraheight = waterheight;
5537         }
5538         else
5539         {
5540                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5541                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5542                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5543                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5544         }
5545
5546         // allocate textures as needed
5547         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))
5548         {
5549                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5550                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5551                 {
5552                         if (p->texture_refraction)
5553                                 R_FreeTexture(p->texture_refraction);
5554                         p->texture_refraction = NULL;
5555                         if (p->fbo_refraction)
5556                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5557                         p->fbo_refraction = 0;
5558                         if (p->texture_reflection)
5559                                 R_FreeTexture(p->texture_reflection);
5560                         p->texture_reflection = NULL;
5561                         if (p->fbo_reflection)
5562                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5563                         p->fbo_reflection = 0;
5564                         if (p->texture_camera)
5565                                 R_FreeTexture(p->texture_camera);
5566                         p->texture_camera = NULL;
5567                         if (p->fbo_camera)
5568                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5569                         p->fbo_camera = 0;
5570                 }
5571                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5572                 r_fb.water.texturewidth = texturewidth;
5573                 r_fb.water.textureheight = textureheight;
5574                 r_fb.water.camerawidth = camerawidth;
5575                 r_fb.water.cameraheight = cameraheight;
5576         }
5577
5578         if (r_fb.water.texturewidth)
5579         {
5580                 int scaledwidth, scaledheight;
5581
5582                 r_fb.water.enabled = true;
5583
5584                 // water resolution is usually reduced
5585                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5586                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5587                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5588
5589                 // set up variables that will be used in shader setup
5590                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5591                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5592                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5593                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5594         }
5595
5596         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5597         r_fb.water.numwaterplanes = 0;
5598 }
5599
5600 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5601 {
5602         int planeindex, bestplaneindex, vertexindex;
5603         vec3_t mins, maxs, normal, center, v, n;
5604         vec_t planescore, bestplanescore;
5605         mplane_t plane;
5606         r_waterstate_waterplane_t *p;
5607         texture_t *t = R_GetCurrentTexture(surface->texture);
5608
5609         rsurface.texture = t;
5610         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5611         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5612         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5613                 return;
5614         // average the vertex normals, find the surface bounds (after deformvertexes)
5615         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5616         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5617         VectorCopy(n, normal);
5618         VectorCopy(v, mins);
5619         VectorCopy(v, maxs);
5620         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5621         {
5622                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5623                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5624                 VectorAdd(normal, n, normal);
5625                 mins[0] = min(mins[0], v[0]);
5626                 mins[1] = min(mins[1], v[1]);
5627                 mins[2] = min(mins[2], v[2]);
5628                 maxs[0] = max(maxs[0], v[0]);
5629                 maxs[1] = max(maxs[1], v[1]);
5630                 maxs[2] = max(maxs[2], v[2]);
5631         }
5632         VectorNormalize(normal);
5633         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5634
5635         VectorCopy(normal, plane.normal);
5636         VectorNormalize(plane.normal);
5637         plane.dist = DotProduct(center, plane.normal);
5638         PlaneClassify(&plane);
5639         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5640         {
5641                 // skip backfaces (except if nocullface is set)
5642 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5643 //                      return;
5644                 VectorNegate(plane.normal, plane.normal);
5645                 plane.dist *= -1;
5646                 PlaneClassify(&plane);
5647         }
5648
5649
5650         // find a matching plane if there is one
5651         bestplaneindex = -1;
5652         bestplanescore = 1048576.0f;
5653         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5654         {
5655                 if(p->camera_entity == t->camera_entity)
5656                 {
5657                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5658                         if (bestplaneindex < 0 || bestplanescore > planescore)
5659                         {
5660                                 bestplaneindex = planeindex;
5661                                 bestplanescore = planescore;
5662                         }
5663                 }
5664         }
5665         planeindex = bestplaneindex;
5666         p = r_fb.water.waterplanes + planeindex;
5667
5668         // if this surface does not fit any known plane rendered this frame, add one
5669         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5670         {
5671                 // store the new plane
5672                 planeindex = r_fb.water.numwaterplanes++;
5673                 p = r_fb.water.waterplanes + planeindex;
5674                 p->plane = plane;
5675                 // clear materialflags and pvs
5676                 p->materialflags = 0;
5677                 p->pvsvalid = false;
5678                 p->camera_entity = t->camera_entity;
5679                 VectorCopy(mins, p->mins);
5680                 VectorCopy(maxs, p->maxs);
5681         }
5682         else
5683         {
5684                 // merge mins/maxs when we're adding this surface to the plane
5685                 p->mins[0] = min(p->mins[0], mins[0]);
5686                 p->mins[1] = min(p->mins[1], mins[1]);
5687                 p->mins[2] = min(p->mins[2], mins[2]);
5688                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5689                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5690                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5691         }
5692         // merge this surface's materialflags into the waterplane
5693         p->materialflags |= t->currentmaterialflags;
5694         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5695         {
5696                 // merge this surface's PVS into the waterplane
5697                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5698                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5699                 {
5700                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5701                         p->pvsvalid = true;
5702                 }
5703         }
5704 }
5705
5706 extern cvar_t r_drawparticles;
5707 extern cvar_t r_drawdecals;
5708
5709 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5710 {
5711         int myscissor[4];
5712         r_refdef_view_t originalview;
5713         r_refdef_view_t myview;
5714         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;
5715         r_waterstate_waterplane_t *p;
5716         vec3_t visorigin;
5717         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5718         char vabuf[1024];
5719
5720         originalview = r_refdef.view;
5721
5722         // lowquality hack, temporarily shut down some cvars and restore afterwards
5723         qualityreduction = r_water_lowquality.integer;
5724         if (qualityreduction > 0)
5725         {
5726                 if (qualityreduction >= 1)
5727                 {
5728                         old_r_shadows = r_shadows.integer;
5729                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5730                         old_r_dlight = r_shadow_realtime_dlight.integer;
5731                         Cvar_SetValueQuick(&r_shadows, 0);
5732                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5733                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5734                 }
5735                 if (qualityreduction >= 2)
5736                 {
5737                         old_r_dynamic = r_dynamic.integer;
5738                         old_r_particles = r_drawparticles.integer;
5739                         old_r_decals = r_drawdecals.integer;
5740                         Cvar_SetValueQuick(&r_dynamic, 0);
5741                         Cvar_SetValueQuick(&r_drawparticles, 0);
5742                         Cvar_SetValueQuick(&r_drawdecals, 0);
5743                 }
5744         }
5745
5746         // make sure enough textures are allocated
5747         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5748         {
5749                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5750                 {
5751                         if (!p->texture_refraction)
5752                                 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);
5753                         if (!p->texture_refraction)
5754                                 goto error;
5755                         if (usewaterfbo)
5756                         {
5757                                 if (r_fb.water.depthtexture == NULL)
5758                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5759                                 if (p->fbo_refraction == 0)
5760                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5761                         }
5762                 }
5763                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5764                 {
5765                         if (!p->texture_camera)
5766                                 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);
5767                         if (!p->texture_camera)
5768                                 goto error;
5769                         if (usewaterfbo)
5770                         {
5771                                 if (r_fb.water.depthtexture == NULL)
5772                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5773                                 if (p->fbo_camera == 0)
5774                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5775                         }
5776                 }
5777
5778                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5779                 {
5780                         if (!p->texture_reflection)
5781                                 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);
5782                         if (!p->texture_reflection)
5783                                 goto error;
5784                         if (usewaterfbo)
5785                         {
5786                                 if (r_fb.water.depthtexture == NULL)
5787                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5788                                 if (p->fbo_reflection == 0)
5789                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5790                         }
5791                 }
5792         }
5793
5794         // render views
5795         r_refdef.view = originalview;
5796         r_refdef.view.showdebug = false;
5797         r_refdef.view.width = r_fb.water.waterwidth;
5798         r_refdef.view.height = r_fb.water.waterheight;
5799         r_refdef.view.useclipplane = true;
5800         myview = r_refdef.view;
5801         r_fb.water.renderingscene = true;
5802         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5803         {
5804                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5805                 {
5806                         r_refdef.view = myview;
5807                         if(r_water_scissormode.integer)
5808                         {
5809                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5810                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5811                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5812                         }
5813
5814                         // render reflected scene and copy into texture
5815                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5816                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5817                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5818                         r_refdef.view.clipplane = p->plane;
5819                         // reverse the cullface settings for this render
5820                         r_refdef.view.cullface_front = GL_FRONT;
5821                         r_refdef.view.cullface_back = GL_BACK;
5822                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5823                         {
5824                                 r_refdef.view.usecustompvs = true;
5825                                 if (p->pvsvalid)
5826                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5827                                 else
5828                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5829                         }
5830
5831                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5832                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5833                         R_ClearScreen(r_refdef.fogenabled);
5834                         if(r_water_scissormode.integer & 2)
5835                                 R_View_UpdateWithScissor(myscissor);
5836                         else
5837                                 R_View_Update();
5838                         if(r_water_scissormode.integer & 1)
5839                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5840                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5841
5842                         if (!p->fbo_reflection)
5843                                 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);
5844                         r_fb.water.hideplayer = false;
5845                 }
5846
5847                 // render the normal view scene and copy into texture
5848                 // (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)
5849                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5850                 {
5851                         r_refdef.view = myview;
5852                         if(r_water_scissormode.integer)
5853                         {
5854                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5855                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5856                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5857                         }
5858
5859                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5860
5861                         r_refdef.view.clipplane = p->plane;
5862                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5863                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5864
5865                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5866                         {
5867                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5868                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5869                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5870                                 R_RenderView_UpdateViewVectors();
5871                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5872                                 {
5873                                         r_refdef.view.usecustompvs = true;
5874                                         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);
5875                                 }
5876                         }
5877
5878                         PlaneClassify(&r_refdef.view.clipplane);
5879
5880                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5881                         R_ClearScreen(r_refdef.fogenabled);
5882                         if(r_water_scissormode.integer & 2)
5883                                 R_View_UpdateWithScissor(myscissor);
5884                         else
5885                                 R_View_Update();
5886                         if(r_water_scissormode.integer & 1)
5887                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5888                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5889
5890                         if (!p->fbo_refraction)
5891                                 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);
5892                         r_fb.water.hideplayer = false;
5893                 }
5894                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5895                 {
5896                         r_refdef.view = myview;
5897
5898                         r_refdef.view.clipplane = p->plane;
5899                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5900                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5901
5902                         r_refdef.view.width = r_fb.water.camerawidth;
5903                         r_refdef.view.height = r_fb.water.cameraheight;
5904                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5905                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5906                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5907                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5908
5909                         if(p->camera_entity)
5910                         {
5911                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5912                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5913                         }
5914
5915                         // note: all of the view is used for displaying... so
5916                         // there is no use in scissoring
5917
5918                         // reverse the cullface settings for this render
5919                         r_refdef.view.cullface_front = GL_FRONT;
5920                         r_refdef.view.cullface_back = GL_BACK;
5921                         // also reverse the view matrix
5922                         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
5923                         R_RenderView_UpdateViewVectors();
5924                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5925                         {
5926                                 r_refdef.view.usecustompvs = true;
5927                                 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);
5928                         }
5929                         
5930                         // camera needs no clipplane
5931                         r_refdef.view.useclipplane = false;
5932
5933                         PlaneClassify(&r_refdef.view.clipplane);
5934
5935                         r_fb.water.hideplayer = false;
5936
5937                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5938                         R_ClearScreen(r_refdef.fogenabled);
5939                         R_View_Update();
5940                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5941
5942                         if (!p->fbo_camera)
5943                                 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);
5944                         r_fb.water.hideplayer = false;
5945                 }
5946
5947         }
5948         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5949         r_fb.water.renderingscene = false;
5950         r_refdef.view = originalview;
5951         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5952         if (!r_fb.water.depthtexture)
5953                 R_ClearScreen(r_refdef.fogenabled);
5954         R_View_Update();
5955         goto finish;
5956 error:
5957         r_refdef.view = originalview;
5958         r_fb.water.renderingscene = false;
5959         Cvar_SetValueQuick(&r_water, 0);
5960         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5961 finish:
5962         // lowquality hack, restore cvars
5963         if (qualityreduction > 0)
5964         {
5965                 if (qualityreduction >= 1)
5966                 {
5967                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5968                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5969                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5970                 }
5971                 if (qualityreduction >= 2)
5972                 {
5973                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5974                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5975                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5976                 }
5977         }
5978 }
5979
5980 static void R_Bloom_StartFrame(void)
5981 {
5982         int i;
5983         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5984         int viewwidth, viewheight;
5985         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5986         textype_t textype = TEXTYPE_COLORBUFFER;
5987
5988         switch (vid.renderpath)
5989         {
5990         case RENDERPATH_GL20:
5991                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5992                 if (vid.support.ext_framebuffer_object)
5993                 {
5994                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5995                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5996                 }
5997                 break;
5998         case RENDERPATH_GL11:
5999         case RENDERPATH_GL13:
6000         case RENDERPATH_GLES1:
6001         case RENDERPATH_GLES2:
6002         case RENDERPATH_D3D9:
6003         case RENDERPATH_D3D10:
6004         case RENDERPATH_D3D11:
6005                 r_fb.usedepthtextures = false;
6006                 break;
6007         case RENDERPATH_SOFT:
6008                 r_fb.usedepthtextures = true;
6009                 break;
6010         }
6011
6012         if (r_viewscale_fpsscaling.integer)
6013         {
6014                 double actualframetime;
6015                 double targetframetime;
6016                 double adjust;
6017                 actualframetime = r_refdef.lastdrawscreentime;
6018                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6019                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6020                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6021                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6022                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6023                 viewscalefpsadjusted += adjust;
6024                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6025         }
6026         else
6027                 viewscalefpsadjusted = 1.0f;
6028
6029         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6030
6031         switch(vid.renderpath)
6032         {
6033         case RENDERPATH_GL20:
6034         case RENDERPATH_D3D9:
6035         case RENDERPATH_D3D10:
6036         case RENDERPATH_D3D11:
6037         case RENDERPATH_SOFT:
6038         case RENDERPATH_GLES2:
6039                 break;
6040         case RENDERPATH_GL11:
6041         case RENDERPATH_GL13:
6042         case RENDERPATH_GLES1:
6043                 return;
6044         }
6045
6046         // set bloomwidth and bloomheight to the bloom resolution that will be
6047         // used (often less than the screen resolution for faster rendering)
6048         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6049         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6050         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6051         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6052         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6053
6054         // calculate desired texture sizes
6055         if (vid.support.arb_texture_non_power_of_two)
6056         {
6057                 screentexturewidth = vid.width;
6058                 screentextureheight = vid.height;
6059                 bloomtexturewidth = r_fb.bloomwidth;
6060                 bloomtextureheight = r_fb.bloomheight;
6061         }
6062         else
6063         {
6064                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6065                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6066                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6067                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6068         }
6069
6070         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))
6071         {
6072                 Cvar_SetValueQuick(&r_bloom, 0);
6073                 Cvar_SetValueQuick(&r_motionblur, 0);
6074                 Cvar_SetValueQuick(&r_damageblur, 0);
6075         }
6076
6077         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6078          && !r_bloom.integer
6079          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6080          && !useviewfbo
6081          && r_viewscale.value == 1.0f
6082          && !r_viewscale_fpsscaling.integer)
6083                 screentexturewidth = screentextureheight = 0;
6084         if (!r_bloom.integer)
6085                 bloomtexturewidth = bloomtextureheight = 0;
6086
6087         // allocate textures as needed
6088         if (r_fb.screentexturewidth != screentexturewidth
6089          || r_fb.screentextureheight != screentextureheight
6090          || r_fb.bloomtexturewidth != bloomtexturewidth
6091          || r_fb.bloomtextureheight != bloomtextureheight
6092          || r_fb.textype != textype
6093          || useviewfbo != (r_fb.fbo != 0))
6094         {
6095                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6096                 {
6097                         if (r_fb.bloomtexture[i])
6098                                 R_FreeTexture(r_fb.bloomtexture[i]);
6099                         r_fb.bloomtexture[i] = NULL;
6100
6101                         if (r_fb.bloomfbo[i])
6102                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6103                         r_fb.bloomfbo[i] = 0;
6104                 }
6105
6106                 if (r_fb.fbo)
6107                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6108                 r_fb.fbo = 0;
6109
6110                 if (r_fb.colortexture)
6111                         R_FreeTexture(r_fb.colortexture);
6112                 r_fb.colortexture = NULL;
6113
6114                 if (r_fb.depthtexture)
6115                         R_FreeTexture(r_fb.depthtexture);
6116                 r_fb.depthtexture = NULL;
6117
6118                 if (r_fb.ghosttexture)
6119                         R_FreeTexture(r_fb.ghosttexture);
6120                 r_fb.ghosttexture = NULL;
6121
6122                 r_fb.screentexturewidth = screentexturewidth;
6123                 r_fb.screentextureheight = screentextureheight;
6124                 r_fb.bloomtexturewidth = bloomtexturewidth;
6125                 r_fb.bloomtextureheight = bloomtextureheight;
6126                 r_fb.textype = textype;
6127
6128                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6129                 {
6130                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6131                                 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);
6132                         r_fb.ghosttexture_valid = false;
6133                         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);
6134                         if (useviewfbo)
6135                         {
6136                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6137                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6138                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6139                         }
6140                 }
6141
6142                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6143                 {
6144                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6145                         {
6146                                 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);
6147                                 if (useviewfbo)
6148                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6149                         }
6150                 }
6151         }
6152
6153         // bloom texture is a different resolution
6154         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6155         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6156         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6157         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6158         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6159
6160         // set up a texcoord array for the full resolution screen image
6161         // (we have to keep this around to copy back during final render)
6162         r_fb.screentexcoord2f[0] = 0;
6163         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6164         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6165         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6166         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6167         r_fb.screentexcoord2f[5] = 0;
6168         r_fb.screentexcoord2f[6] = 0;
6169         r_fb.screentexcoord2f[7] = 0;
6170
6171         // set up a texcoord array for the reduced resolution bloom image
6172         // (which will be additive blended over the screen image)
6173         r_fb.bloomtexcoord2f[0] = 0;
6174         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6175         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6176         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6177         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6178         r_fb.bloomtexcoord2f[5] = 0;
6179         r_fb.bloomtexcoord2f[6] = 0;
6180         r_fb.bloomtexcoord2f[7] = 0;
6181
6182         switch(vid.renderpath)
6183         {
6184         case RENDERPATH_GL11:
6185         case RENDERPATH_GL13:
6186         case RENDERPATH_GL20:
6187         case RENDERPATH_SOFT:
6188         case RENDERPATH_GLES1:
6189         case RENDERPATH_GLES2:
6190                 break;
6191         case RENDERPATH_D3D9:
6192         case RENDERPATH_D3D10:
6193         case RENDERPATH_D3D11:
6194                 {
6195                         int i;
6196                         for (i = 0;i < 4;i++)
6197                         {
6198                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6199                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6200                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6201                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6202                         }
6203                 }
6204                 break;
6205         }
6206
6207         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);
6208
6209         if (r_fb.fbo)
6210                 r_refdef.view.clear = true;
6211 }
6212
6213 static void R_Bloom_MakeTexture(void)
6214 {
6215         int x, range, dir;
6216         float xoffset, yoffset, r, brighten;
6217         rtexture_t *intex;
6218         float colorscale = r_bloom_colorscale.value;
6219
6220         r_refdef.stats.bloom++;
6221
6222         if (!r_fb.fbo)
6223         {
6224                 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);
6225                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6226         }
6227
6228         // scale down screen texture to the bloom texture size
6229         CHECKGLERROR
6230         r_fb.bloomindex = 0;
6231         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6232         R_SetViewport(&r_fb.bloomviewport);
6233         GL_BlendFunc(GL_ONE, GL_ZERO);
6234         GL_Color(colorscale, colorscale, colorscale, 1);
6235         // 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...
6236         switch(vid.renderpath)
6237         {
6238         case RENDERPATH_GL11:
6239         case RENDERPATH_GL13:
6240         case RENDERPATH_GL20:
6241         case RENDERPATH_GLES1:
6242         case RENDERPATH_GLES2:
6243         case RENDERPATH_SOFT:
6244                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6245                 break;
6246         case RENDERPATH_D3D9:
6247         case RENDERPATH_D3D10:
6248         case RENDERPATH_D3D11:
6249                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6250                 break;
6251         }
6252         // TODO: do boxfilter scale-down in shader?
6253         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6254         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6255         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6256
6257         // we now have a properly scaled bloom image
6258         if (!r_fb.bloomfbo[r_fb.bloomindex])
6259         {
6260                 // copy it into the bloom texture
6261                 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);
6262                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6263         }
6264
6265         // multiply bloom image by itself as many times as desired
6266         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6267         {
6268                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6269                 r_fb.bloomindex ^= 1;
6270                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6271                 x *= 2;
6272                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6273                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6274                 {
6275                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6276                         GL_Color(r,r,r,1); // apply fix factor
6277                 }
6278                 else
6279                 {
6280                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6281                         GL_Color(1,1,1,1); // no fix factor supported here
6282                 }
6283                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6284                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6285                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6286                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6287
6288                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6289                 {
6290                         // copy the darkened image to a texture
6291                         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);
6292                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6293                 }
6294         }
6295
6296         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6297         brighten = r_bloom_brighten.value;
6298         brighten = sqrt(brighten);
6299         if(range >= 1)
6300                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6301
6302         for (dir = 0;dir < 2;dir++)
6303         {
6304                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6305                 r_fb.bloomindex ^= 1;
6306                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6307                 // blend on at multiple vertical offsets to achieve a vertical blur
6308                 // TODO: do offset blends using GLSL
6309                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6310                 GL_BlendFunc(GL_ONE, GL_ZERO);
6311                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6312                 for (x = -range;x <= range;x++)
6313                 {
6314                         if (!dir){xoffset = 0;yoffset = x;}
6315                         else {xoffset = x;yoffset = 0;}
6316                         xoffset /= (float)r_fb.bloomtexturewidth;
6317                         yoffset /= (float)r_fb.bloomtextureheight;
6318                         // compute a texcoord array with the specified x and y offset
6319                         r_fb.offsettexcoord2f[0] = xoffset+0;
6320                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6321                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6322                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6323                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6324                         r_fb.offsettexcoord2f[5] = yoffset+0;
6325                         r_fb.offsettexcoord2f[6] = xoffset+0;
6326                         r_fb.offsettexcoord2f[7] = yoffset+0;
6327                         // this r value looks like a 'dot' particle, fading sharply to
6328                         // black at the edges
6329                         // (probably not realistic but looks good enough)
6330                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6331                         //r = brighten/(range*2+1);
6332                         r = brighten / (range * 2 + 1);
6333                         if(range >= 1)
6334                                 r *= (1 - x*x/(float)(range*range));
6335                         GL_Color(r, r, r, 1);
6336                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6337                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6338                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6339                         GL_BlendFunc(GL_ONE, GL_ONE);
6340                 }
6341
6342                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6343                 {
6344                         // copy the vertically or horizontally blurred bloom view to a texture
6345                         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);
6346                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6347                 }
6348         }
6349 }
6350
6351 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6352 {
6353         unsigned int permutation;
6354         float uservecs[4][4];
6355
6356         switch (vid.renderpath)
6357         {
6358         case RENDERPATH_GL20:
6359         case RENDERPATH_D3D9:
6360         case RENDERPATH_D3D10:
6361         case RENDERPATH_D3D11:
6362         case RENDERPATH_SOFT:
6363         case RENDERPATH_GLES2:
6364                 permutation =
6365                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6366                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6367                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6368                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6369                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6370
6371                 if (r_fb.colortexture)
6372                 {
6373                         if (!r_fb.fbo)
6374                         {
6375                                 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);
6376                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6377                         }
6378
6379                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6380                         {
6381                                 // declare variables
6382                                 float blur_factor, blur_mouseaccel, blur_velocity;
6383                                 static float blur_average; 
6384                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6385
6386                                 // set a goal for the factoring
6387                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6388                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6389                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6390                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6391                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6392                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6393
6394                                 // from the goal, pick an averaged value between goal and last value
6395                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6396                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6397
6398                                 // enforce minimum amount of blur 
6399                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6400
6401                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6402
6403                                 // calculate values into a standard alpha
6404                                 cl.motionbluralpha = 1 - exp(-
6405                                                 (
6406                                                  (r_motionblur.value * blur_factor / 80)
6407                                                  +
6408                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6409                                                 )
6410                                                 /
6411                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6412                                           );
6413
6414                                 // randomization for the blur value to combat persistent ghosting
6415                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6416                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6417
6418                                 // apply the blur
6419                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6420                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6421                                 {
6422                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6423                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6424                                         switch(vid.renderpath)
6425                                         {
6426                                         case RENDERPATH_GL11:
6427                                         case RENDERPATH_GL13:
6428                                         case RENDERPATH_GL20:
6429                                         case RENDERPATH_GLES1:
6430                                         case RENDERPATH_GLES2:
6431                                         case RENDERPATH_SOFT:
6432                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6433                                                 break;
6434                                         case RENDERPATH_D3D9:
6435                                         case RENDERPATH_D3D10:
6436                                         case RENDERPATH_D3D11:
6437                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6438                                                 break;
6439                                         }
6440                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6441                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6442                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6443                                 }
6444
6445                                 // updates old view angles for next pass
6446                                 VectorCopy(cl.viewangles, blur_oldangles);
6447
6448                                 // copy view into the ghost texture
6449                                 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);
6450                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6451                                 r_fb.ghosttexture_valid = true;
6452                         }
6453                 }
6454                 else
6455                 {
6456                         // no r_fb.colortexture means we're rendering to the real fb
6457                         // we may still have to do view tint...
6458                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6459                         {
6460                                 // apply a color tint to the whole view
6461                                 R_ResetViewRendering2D(0, NULL, NULL);
6462                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6463                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6464                                 R_SetupShader_Generic_NoTexture(false, true);
6465                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6466                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6467                         }
6468                         break; // no screen processing, no bloom, skip it
6469                 }
6470
6471                 if (r_fb.bloomtexture[0])
6472                 {
6473                         // make the bloom texture
6474                         R_Bloom_MakeTexture();
6475                 }
6476
6477 #if _MSC_VER >= 1400
6478 #define sscanf sscanf_s
6479 #endif
6480                 memset(uservecs, 0, sizeof(uservecs));
6481                 if (r_glsl_postprocess_uservec1_enable.integer)
6482                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6483                 if (r_glsl_postprocess_uservec2_enable.integer)
6484                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6485                 if (r_glsl_postprocess_uservec3_enable.integer)
6486                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6487                 if (r_glsl_postprocess_uservec4_enable.integer)
6488                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6489
6490                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6491                 GL_Color(1, 1, 1, 1);
6492                 GL_BlendFunc(GL_ONE, GL_ZERO);
6493
6494                 switch(vid.renderpath)
6495                 {
6496                 case RENDERPATH_GL20:
6497                 case RENDERPATH_GLES2:
6498                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6499                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6500                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6501                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6502                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6503                         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]);
6504                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6505                         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]);
6506                         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]);
6507                         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]);
6508                         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]);
6509                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6510                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6511                         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);
6512                         break;
6513                 case RENDERPATH_D3D9:
6514 #ifdef SUPPORTD3D
6515                         // 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...
6516                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6517                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6518                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6519                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6520                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6521                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6522                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6523                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6524                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6525                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6526                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6527                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6528                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6529                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6530 #endif
6531                         break;
6532                 case RENDERPATH_D3D10:
6533                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6534                         break;
6535                 case RENDERPATH_D3D11:
6536                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6537                         break;
6538                 case RENDERPATH_SOFT:
6539                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6540                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6541                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6542                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6543                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6544                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6545                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6546                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6547                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6548                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6549                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6550                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6551                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6552                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6553                         break;
6554                 default:
6555                         break;
6556                 }
6557                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6558                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6559                 break;
6560         case RENDERPATH_GL11:
6561         case RENDERPATH_GL13:
6562         case RENDERPATH_GLES1:
6563                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6564                 {
6565                         // apply a color tint to the whole view
6566                         R_ResetViewRendering2D(0, NULL, NULL);
6567                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6568                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6569                         R_SetupShader_Generic_NoTexture(false, true);
6570                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6571                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6572                 }
6573                 break;
6574         }
6575 }
6576
6577 matrix4x4_t r_waterscrollmatrix;
6578
6579 void R_UpdateFog(void)
6580 {
6581         // Nehahra fog
6582         if (gamemode == GAME_NEHAHRA)
6583         {
6584                 if (gl_fogenable.integer)
6585                 {
6586                         r_refdef.oldgl_fogenable = true;
6587                         r_refdef.fog_density = gl_fogdensity.value;
6588                         r_refdef.fog_red = gl_fogred.value;
6589                         r_refdef.fog_green = gl_foggreen.value;
6590                         r_refdef.fog_blue = gl_fogblue.value;
6591                         r_refdef.fog_alpha = 1;
6592                         r_refdef.fog_start = 0;
6593                         r_refdef.fog_end = gl_skyclip.value;
6594                         r_refdef.fog_height = 1<<30;
6595                         r_refdef.fog_fadedepth = 128;
6596                 }
6597                 else if (r_refdef.oldgl_fogenable)
6598                 {
6599                         r_refdef.oldgl_fogenable = false;
6600                         r_refdef.fog_density = 0;
6601                         r_refdef.fog_red = 0;
6602                         r_refdef.fog_green = 0;
6603                         r_refdef.fog_blue = 0;
6604                         r_refdef.fog_alpha = 0;
6605                         r_refdef.fog_start = 0;
6606                         r_refdef.fog_end = 0;
6607                         r_refdef.fog_height = 1<<30;
6608                         r_refdef.fog_fadedepth = 128;
6609                 }
6610         }
6611
6612         // fog parms
6613         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6614         r_refdef.fog_start = max(0, r_refdef.fog_start);
6615         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6616
6617         if (r_refdef.fog_density && r_drawfog.integer)
6618         {
6619                 r_refdef.fogenabled = true;
6620                 // this is the point where the fog reaches 0.9986 alpha, which we
6621                 // consider a good enough cutoff point for the texture
6622                 // (0.9986 * 256 == 255.6)
6623                 if (r_fog_exp2.integer)
6624                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6625                 else
6626                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6627                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6628                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6629                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6630                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6631                         R_BuildFogHeightTexture();
6632                 // fog color was already set
6633                 // update the fog texture
6634                 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)
6635                         R_BuildFogTexture();
6636                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6637                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6638         }
6639         else
6640                 r_refdef.fogenabled = false;
6641
6642         // fog color
6643         if (r_refdef.fog_density)
6644         {
6645                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6646                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6647                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6648
6649                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6650                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6651                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6652                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6653
6654                 {
6655                         vec3_t fogvec;
6656                         VectorCopy(r_refdef.fogcolor, fogvec);
6657                         //   color.rgb *= ContrastBoost * SceneBrightness;
6658                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6659                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6660                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6661                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6662                 }
6663         }
6664 }
6665
6666 void R_UpdateVariables(void)
6667 {
6668         R_Textures_Frame();
6669
6670         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6671
6672         r_refdef.farclip = r_farclip_base.value;
6673         if (r_refdef.scene.worldmodel)
6674                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6675         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6676
6677         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6678                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6679         r_refdef.polygonfactor = 0;
6680         r_refdef.polygonoffset = 0;
6681         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6682         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6683
6684         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6685         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6686         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6687         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6688         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6689         if (FAKELIGHT_ENABLED)
6690         {
6691                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6692         }
6693         else if (r_refdef.scene.worldmodel)
6694         {
6695                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6696         }
6697         if (r_showsurfaces.integer)
6698         {
6699                 r_refdef.scene.rtworld = false;
6700                 r_refdef.scene.rtworldshadows = false;
6701                 r_refdef.scene.rtdlight = false;
6702                 r_refdef.scene.rtdlightshadows = false;
6703                 r_refdef.lightmapintensity = 0;
6704         }
6705
6706         switch(vid.renderpath)
6707         {
6708         case RENDERPATH_GL20:
6709         case RENDERPATH_D3D9:
6710         case RENDERPATH_D3D10:
6711         case RENDERPATH_D3D11:
6712         case RENDERPATH_SOFT:
6713         case RENDERPATH_GLES2:
6714                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6715                 {
6716                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6717                         {
6718                                 // build GLSL gamma texture
6719 #define RAMPWIDTH 256
6720                                 unsigned short ramp[RAMPWIDTH * 3];
6721                                 unsigned char rampbgr[RAMPWIDTH][4];
6722                                 int i;
6723
6724                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6725
6726                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6727                                 for(i = 0; i < RAMPWIDTH; ++i)
6728                                 {
6729                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6730                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6731                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6732                                         rampbgr[i][3] = 0;
6733                                 }
6734                                 if (r_texture_gammaramps)
6735                                 {
6736                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6737                                 }
6738                                 else
6739                                 {
6740                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6741                                 }
6742                         }
6743                 }
6744                 else
6745                 {
6746                         // remove GLSL gamma texture
6747                 }
6748                 break;
6749         case RENDERPATH_GL11:
6750         case RENDERPATH_GL13:
6751         case RENDERPATH_GLES1:
6752                 break;
6753         }
6754 }
6755
6756 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6757 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6758 /*
6759 ================
6760 R_SelectScene
6761 ================
6762 */
6763 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6764         if( scenetype != r_currentscenetype ) {
6765                 // store the old scenetype
6766                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6767                 r_currentscenetype = scenetype;
6768                 // move in the new scene
6769                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6770         }
6771 }
6772
6773 /*
6774 ================
6775 R_GetScenePointer
6776 ================
6777 */
6778 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6779 {
6780         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6781         if( scenetype == r_currentscenetype ) {
6782                 return &r_refdef.scene;
6783         } else {
6784                 return &r_scenes_store[ scenetype ];
6785         }
6786 }
6787
6788 static int R_SortEntities_Compare(const void *ap, const void *bp)
6789 {
6790         const entity_render_t *a = *(const entity_render_t **)ap;
6791         const entity_render_t *b = *(const entity_render_t **)bp;
6792
6793         // 1. compare model
6794         if(a->model < b->model)
6795                 return -1;
6796         if(a->model > b->model)
6797                 return +1;
6798
6799         // 2. compare skin
6800         // TODO possibly calculate the REAL skinnum here first using
6801         // skinscenes?
6802         if(a->skinnum < b->skinnum)
6803                 return -1;
6804         if(a->skinnum > b->skinnum)
6805                 return +1;
6806
6807         // everything we compared is equal
6808         return 0;
6809 }
6810 static void R_SortEntities(void)
6811 {
6812         // below or equal 2 ents, sorting never gains anything
6813         if(r_refdef.scene.numentities <= 2)
6814                 return;
6815         // sort
6816         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6817 }
6818
6819 /*
6820 ================
6821 R_RenderView
6822 ================
6823 */
6824 int dpsoftrast_test;
6825 extern cvar_t r_shadow_bouncegrid;
6826 void R_RenderView(void)
6827 {
6828         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6829         int fbo;
6830         rtexture_t *depthtexture;
6831         rtexture_t *colortexture;
6832
6833         dpsoftrast_test = r_test.integer;
6834
6835         if (r_timereport_active)
6836                 R_TimeReport("start");
6837         r_textureframe++; // used only by R_GetCurrentTexture
6838         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6839
6840         if(R_CompileShader_CheckStaticParms())
6841                 R_GLSL_Restart_f();
6842
6843         if (!r_drawentities.integer)
6844                 r_refdef.scene.numentities = 0;
6845         else if (r_sortentities.integer)
6846                 R_SortEntities();
6847
6848         R_AnimCache_ClearCache();
6849         R_FrameData_NewFrame();
6850
6851         /* adjust for stereo display */
6852         if(R_Stereo_Active())
6853         {
6854                 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);
6855                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6856         }
6857
6858         if (r_refdef.view.isoverlay)
6859         {
6860                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6861                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6862                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6863                 R_TimeReport("depthclear");
6864
6865                 r_refdef.view.showdebug = false;
6866
6867                 r_fb.water.enabled = false;
6868                 r_fb.water.numwaterplanes = 0;
6869
6870                 R_RenderScene(0, NULL, NULL);
6871
6872                 r_refdef.view.matrix = originalmatrix;
6873
6874                 CHECKGLERROR
6875                 return;
6876         }
6877
6878         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6879         {
6880                 r_refdef.view.matrix = originalmatrix;
6881                 return;
6882         }
6883
6884         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6885
6886         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6887                 // in sRGB fallback, behave similar to true sRGB: convert this
6888                 // value from linear to sRGB
6889                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6890
6891         R_RenderView_UpdateViewVectors();
6892
6893         R_Shadow_UpdateWorldLightSelection();
6894
6895         R_Bloom_StartFrame();
6896         R_Water_StartFrame();
6897
6898         // now we probably have an fbo to render into
6899         fbo = r_fb.fbo;
6900         depthtexture = r_fb.depthtexture;
6901         colortexture = r_fb.colortexture;
6902
6903         CHECKGLERROR
6904         if (r_timereport_active)
6905                 R_TimeReport("viewsetup");
6906
6907         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6908
6909         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6910         {
6911                 R_ClearScreen(r_refdef.fogenabled);
6912                 if (r_timereport_active)
6913                         R_TimeReport("viewclear");
6914         }
6915         r_refdef.view.clear = true;
6916
6917         r_refdef.view.showdebug = true;
6918
6919         R_View_Update();
6920         if (r_timereport_active)
6921                 R_TimeReport("visibility");
6922
6923         R_Shadow_UpdateBounceGridTexture();
6924         if (r_timereport_active && r_shadow_bouncegrid.integer)
6925                 R_TimeReport("bouncegrid");
6926
6927         r_fb.water.numwaterplanes = 0;
6928         if (r_fb.water.enabled)
6929                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6930
6931         R_RenderScene(fbo, depthtexture, colortexture);
6932         r_fb.water.numwaterplanes = 0;
6933
6934         R_BlendView(fbo, depthtexture, colortexture);
6935         if (r_timereport_active)
6936                 R_TimeReport("blendview");
6937
6938         GL_Scissor(0, 0, vid.width, vid.height);
6939         GL_ScissorTest(false);
6940
6941         r_refdef.view.matrix = originalmatrix;
6942
6943         CHECKGLERROR
6944 }
6945
6946 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6947 {
6948         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6949         {
6950                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6951                 if (r_timereport_active)
6952                         R_TimeReport("waterworld");
6953         }
6954
6955         // don't let sound skip if going slow
6956         if (r_refdef.scene.extraupdate)
6957                 S_ExtraUpdate ();
6958
6959         R_DrawModelsAddWaterPlanes();
6960         if (r_timereport_active)
6961                 R_TimeReport("watermodels");
6962
6963         if (r_fb.water.numwaterplanes)
6964         {
6965                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6966                 if (r_timereport_active)
6967                         R_TimeReport("waterscenes");
6968         }
6969 }
6970
6971 extern cvar_t cl_locs_show;
6972 static void R_DrawLocs(void);
6973 static void R_DrawEntityBBoxes(void);
6974 static void R_DrawModelDecals(void);
6975 extern cvar_t cl_decals_newsystem;
6976 extern qboolean r_shadow_usingdeferredprepass;
6977 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6978 {
6979         qboolean shadowmapping = false;
6980
6981         if (r_timereport_active)
6982                 R_TimeReport("beginscene");
6983
6984         r_refdef.stats.renders++;
6985
6986         R_UpdateFog();
6987
6988         // don't let sound skip if going slow
6989         if (r_refdef.scene.extraupdate)
6990                 S_ExtraUpdate ();
6991
6992         R_MeshQueue_BeginScene();
6993
6994         R_SkyStartFrame();
6995
6996         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);
6997
6998         if (r_timereport_active)
6999                 R_TimeReport("skystartframe");
7000
7001         if (cl.csqc_vidvars.drawworld)
7002         {
7003                 // don't let sound skip if going slow
7004                 if (r_refdef.scene.extraupdate)
7005                         S_ExtraUpdate ();
7006
7007                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7008                 {
7009                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7010                         if (r_timereport_active)
7011                                 R_TimeReport("worldsky");
7012                 }
7013
7014                 if (R_DrawBrushModelsSky() && r_timereport_active)
7015                         R_TimeReport("bmodelsky");
7016
7017                 if (skyrendermasked && skyrenderlater)
7018                 {
7019                         // we have to force off the water clipping plane while rendering sky
7020                         R_SetupView(false, fbo, depthtexture, colortexture);
7021                         R_Sky();
7022                         R_SetupView(true, fbo, depthtexture, colortexture);
7023                         if (r_timereport_active)
7024                                 R_TimeReport("sky");
7025                 }
7026         }
7027
7028         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7029         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7030                 R_Shadow_PrepareModelShadows();
7031         if (r_timereport_active)
7032                 R_TimeReport("preparelights");
7033
7034         if (R_Shadow_ShadowMappingEnabled())
7035                 shadowmapping = true;
7036
7037         if (r_shadow_usingdeferredprepass)
7038                 R_Shadow_DrawPrepass();
7039
7040         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7041         {
7042                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7043                 if (r_timereport_active)
7044                         R_TimeReport("worlddepth");
7045         }
7046         if (r_depthfirst.integer >= 2)
7047         {
7048                 R_DrawModelsDepth();
7049                 if (r_timereport_active)
7050                         R_TimeReport("modeldepth");
7051         }
7052
7053         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7054         {
7055                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7056                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7057                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7058                 // don't let sound skip if going slow
7059                 if (r_refdef.scene.extraupdate)
7060                         S_ExtraUpdate ();
7061         }
7062
7063         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7064         {
7065                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7066                 if (r_timereport_active)
7067                         R_TimeReport("world");
7068         }
7069
7070         // don't let sound skip if going slow
7071         if (r_refdef.scene.extraupdate)
7072                 S_ExtraUpdate ();
7073
7074         R_DrawModels();
7075         if (r_timereport_active)
7076                 R_TimeReport("models");
7077
7078         // don't let sound skip if going slow
7079         if (r_refdef.scene.extraupdate)
7080                 S_ExtraUpdate ();
7081
7082         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7083         {
7084                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7085                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7086                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7087                 // don't let sound skip if going slow
7088                 if (r_refdef.scene.extraupdate)
7089                         S_ExtraUpdate ();
7090         }
7091
7092         if (!r_shadow_usingdeferredprepass)
7093         {
7094                 R_Shadow_DrawLights();
7095                 if (r_timereport_active)
7096                         R_TimeReport("rtlights");
7097         }
7098
7099         // don't let sound skip if going slow
7100         if (r_refdef.scene.extraupdate)
7101                 S_ExtraUpdate ();
7102
7103         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7104         {
7105                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7106                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7107                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7108                 // don't let sound skip if going slow
7109                 if (r_refdef.scene.extraupdate)
7110                         S_ExtraUpdate ();
7111         }
7112
7113         if (cl.csqc_vidvars.drawworld)
7114         {
7115                 if (cl_decals_newsystem.integer)
7116                 {
7117                         R_DrawModelDecals();
7118                         if (r_timereport_active)
7119                                 R_TimeReport("modeldecals");
7120                 }
7121                 else
7122                 {
7123                         R_DrawDecals();
7124                         if (r_timereport_active)
7125                                 R_TimeReport("decals");
7126                 }
7127
7128                 R_DrawParticles();
7129                 if (r_timereport_active)
7130                         R_TimeReport("particles");
7131
7132                 R_DrawExplosions();
7133                 if (r_timereport_active)
7134                         R_TimeReport("explosions");
7135
7136                 R_DrawLightningBeams();
7137                 if (r_timereport_active)
7138                         R_TimeReport("lightning");
7139         }
7140
7141         if (cl.csqc_loaded)
7142                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7143
7144         if (r_refdef.view.showdebug)
7145         {
7146                 if (cl_locs_show.integer)
7147                 {
7148                         R_DrawLocs();
7149                         if (r_timereport_active)
7150                                 R_TimeReport("showlocs");
7151                 }
7152
7153                 if (r_drawportals.integer)
7154                 {
7155                         R_DrawPortals();
7156                         if (r_timereport_active)
7157                                 R_TimeReport("portals");
7158                 }
7159
7160                 if (r_showbboxes.value > 0)
7161                 {
7162                         R_DrawEntityBBoxes();
7163                         if (r_timereport_active)
7164                                 R_TimeReport("bboxes");
7165                 }
7166         }
7167
7168         if (r_transparent.integer)
7169         {
7170                 R_MeshQueue_RenderTransparent();
7171                 if (r_timereport_active)
7172                         R_TimeReport("drawtrans");
7173         }
7174
7175         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))
7176         {
7177                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7178                 if (r_timereport_active)
7179                         R_TimeReport("worlddebug");
7180                 R_DrawModelsDebug();
7181                 if (r_timereport_active)
7182                         R_TimeReport("modeldebug");
7183         }
7184
7185         if (cl.csqc_vidvars.drawworld)
7186         {
7187                 R_Shadow_DrawCoronas();
7188                 if (r_timereport_active)
7189                         R_TimeReport("coronas");
7190         }
7191
7192 #if 0
7193         {
7194                 GL_DepthTest(false);
7195                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7196                 GL_Color(1, 1, 1, 1);
7197                 qglBegin(GL_POLYGON);
7198                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7199                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7200                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7201                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7202                 qglEnd();
7203                 qglBegin(GL_POLYGON);
7204                 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]);
7205                 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]);
7206                 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]);
7207                 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]);
7208                 qglEnd();
7209                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7210         }
7211 #endif
7212
7213         // don't let sound skip if going slow
7214         if (r_refdef.scene.extraupdate)
7215                 S_ExtraUpdate ();
7216 }
7217
7218 static const unsigned short bboxelements[36] =
7219 {
7220         5, 1, 3, 5, 3, 7,
7221         6, 2, 0, 6, 0, 4,
7222         7, 3, 2, 7, 2, 6,
7223         4, 0, 1, 4, 1, 5,
7224         4, 5, 7, 4, 7, 6,
7225         1, 0, 2, 1, 2, 3,
7226 };
7227
7228 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7229 {
7230         int i;
7231         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7232
7233         RSurf_ActiveWorldEntity();
7234
7235         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7236         GL_DepthMask(false);
7237         GL_DepthRange(0, 1);
7238         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7239 //      R_Mesh_ResetTextureState();
7240
7241         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7242         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7243         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7244         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7245         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7246         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7247         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7248         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7249         R_FillColors(color4f, 8, cr, cg, cb, ca);
7250         if (r_refdef.fogenabled)
7251         {
7252                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7253                 {
7254                         f1 = RSurf_FogVertex(v);
7255                         f2 = 1 - f1;
7256                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7257                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7258                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7259                 }
7260         }
7261         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7262         R_Mesh_ResetTextureState();
7263         R_SetupShader_Generic_NoTexture(false, false);
7264         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7265 }
7266
7267 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7268 {
7269         prvm_prog_t *prog = SVVM_prog;
7270         int i;
7271         float color[4];
7272         prvm_edict_t *edict;
7273
7274         // this function draws bounding boxes of server entities
7275         if (!sv.active)
7276                 return;
7277
7278         GL_CullFace(GL_NONE);
7279         R_SetupShader_Generic_NoTexture(false, false);
7280
7281         for (i = 0;i < numsurfaces;i++)
7282         {
7283                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7284                 switch ((int)PRVM_serveredictfloat(edict, solid))
7285                 {
7286                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7287                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7288                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7289                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7290                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7291                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7292                 }
7293                 color[3] *= r_showbboxes.value;
7294                 color[3] = bound(0, color[3], 1);
7295                 GL_DepthTest(!r_showdisabledepthtest.integer);
7296                 GL_CullFace(r_refdef.view.cullface_front);
7297                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7298         }
7299 }
7300
7301 static void R_DrawEntityBBoxes(void)
7302 {
7303         int i;
7304         prvm_edict_t *edict;
7305         vec3_t center;
7306         prvm_prog_t *prog = SVVM_prog;
7307
7308         // this function draws bounding boxes of server entities
7309         if (!sv.active)
7310                 return;
7311
7312         for (i = 0;i < prog->num_edicts;i++)
7313         {
7314                 edict = PRVM_EDICT_NUM(i);
7315                 if (edict->priv.server->free)
7316                         continue;
7317                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7318                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7319                         continue;
7320                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7321                         continue;
7322                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7323                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7324         }
7325 }
7326
7327 static const int nomodelelement3i[24] =
7328 {
7329         5, 2, 0,
7330         5, 1, 2,
7331         5, 0, 3,
7332         5, 3, 1,
7333         0, 2, 4,
7334         2, 1, 4,
7335         3, 0, 4,
7336         1, 3, 4
7337 };
7338
7339 static const unsigned short nomodelelement3s[24] =
7340 {
7341         5, 2, 0,
7342         5, 1, 2,
7343         5, 0, 3,
7344         5, 3, 1,
7345         0, 2, 4,
7346         2, 1, 4,
7347         3, 0, 4,
7348         1, 3, 4
7349 };
7350
7351 static const float nomodelvertex3f[6*3] =
7352 {
7353         -16,   0,   0,
7354          16,   0,   0,
7355           0, -16,   0,
7356           0,  16,   0,
7357           0,   0, -16,
7358           0,   0,  16
7359 };
7360
7361 static const float nomodelcolor4f[6*4] =
7362 {
7363         0.0f, 0.0f, 0.5f, 1.0f,
7364         0.0f, 0.0f, 0.5f, 1.0f,
7365         0.0f, 0.5f, 0.0f, 1.0f,
7366         0.0f, 0.5f, 0.0f, 1.0f,
7367         0.5f, 0.0f, 0.0f, 1.0f,
7368         0.5f, 0.0f, 0.0f, 1.0f
7369 };
7370
7371 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7372 {
7373         int i;
7374         float f1, f2, *c;
7375         float color4f[6*4];
7376
7377         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);
7378
7379         // this is only called once per entity so numsurfaces is always 1, and
7380         // surfacelist is always {0}, so this code does not handle batches
7381
7382         if (rsurface.ent_flags & RENDER_ADDITIVE)
7383         {
7384                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7385                 GL_DepthMask(false);
7386         }
7387         else if (rsurface.colormod[3] < 1)
7388         {
7389                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7390                 GL_DepthMask(false);
7391         }
7392         else
7393         {
7394                 GL_BlendFunc(GL_ONE, GL_ZERO);
7395                 GL_DepthMask(true);
7396         }
7397         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7398         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7399         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7400         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7401         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7402         for (i = 0, c = color4f;i < 6;i++, c += 4)
7403         {
7404                 c[0] *= rsurface.colormod[0];
7405                 c[1] *= rsurface.colormod[1];
7406                 c[2] *= rsurface.colormod[2];
7407                 c[3] *= rsurface.colormod[3];
7408         }
7409         if (r_refdef.fogenabled)
7410         {
7411                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7412                 {
7413                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7414                         f2 = 1 - f1;
7415                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7416                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7417                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7418                 }
7419         }
7420 //      R_Mesh_ResetTextureState();
7421         R_SetupShader_Generic_NoTexture(false, false);
7422         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7423         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7424 }
7425
7426 void R_DrawNoModel(entity_render_t *ent)
7427 {
7428         vec3_t org;
7429         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7430         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7431                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7432         else
7433                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7434 }
7435
7436 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7437 {
7438         vec3_t right1, right2, diff, normal;
7439
7440         VectorSubtract (org2, org1, normal);
7441
7442         // calculate 'right' vector for start
7443         VectorSubtract (r_refdef.view.origin, org1, diff);
7444         CrossProduct (normal, diff, right1);
7445         VectorNormalize (right1);
7446
7447         // calculate 'right' vector for end
7448         VectorSubtract (r_refdef.view.origin, org2, diff);
7449         CrossProduct (normal, diff, right2);
7450         VectorNormalize (right2);
7451
7452         vert[ 0] = org1[0] + width * right1[0];
7453         vert[ 1] = org1[1] + width * right1[1];
7454         vert[ 2] = org1[2] + width * right1[2];
7455         vert[ 3] = org1[0] - width * right1[0];
7456         vert[ 4] = org1[1] - width * right1[1];
7457         vert[ 5] = org1[2] - width * right1[2];
7458         vert[ 6] = org2[0] - width * right2[0];
7459         vert[ 7] = org2[1] - width * right2[1];
7460         vert[ 8] = org2[2] - width * right2[2];
7461         vert[ 9] = org2[0] + width * right2[0];
7462         vert[10] = org2[1] + width * right2[1];
7463         vert[11] = org2[2] + width * right2[2];
7464 }
7465
7466 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)
7467 {
7468         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7469         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7470         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7471         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7472         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7473         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7474         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7475         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7476         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7477         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7478         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7479         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7480 }
7481
7482 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7483 {
7484         int i;
7485         float *vertex3f;
7486         float v[3];
7487         VectorSet(v, x, y, z);
7488         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7489                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7490                         break;
7491         if (i == mesh->numvertices)
7492         {
7493                 if (mesh->numvertices < mesh->maxvertices)
7494                 {
7495                         VectorCopy(v, vertex3f);
7496                         mesh->numvertices++;
7497                 }
7498                 return mesh->numvertices;
7499         }
7500         else
7501                 return i;
7502 }
7503
7504 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7505 {
7506         int i;
7507         int *e, element[3];
7508         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7509         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7510         e = mesh->element3i + mesh->numtriangles * 3;
7511         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7512         {
7513                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7514                 if (mesh->numtriangles < mesh->maxtriangles)
7515                 {
7516                         *e++ = element[0];
7517                         *e++ = element[1];
7518                         *e++ = element[2];
7519                         mesh->numtriangles++;
7520                 }
7521                 element[1] = element[2];
7522         }
7523 }
7524
7525 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7526 {
7527         int i;
7528         int *e, element[3];
7529         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7530         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7531         e = mesh->element3i + mesh->numtriangles * 3;
7532         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7533         {
7534                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7535                 if (mesh->numtriangles < mesh->maxtriangles)
7536                 {
7537                         *e++ = element[0];
7538                         *e++ = element[1];
7539                         *e++ = element[2];
7540                         mesh->numtriangles++;
7541                 }
7542                 element[1] = element[2];
7543         }
7544 }
7545
7546 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7547 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7548 {
7549         int planenum, planenum2;
7550         int w;
7551         int tempnumpoints;
7552         mplane_t *plane, *plane2;
7553         double maxdist;
7554         double temppoints[2][256*3];
7555         // figure out how large a bounding box we need to properly compute this brush
7556         maxdist = 0;
7557         for (w = 0;w < numplanes;w++)
7558                 maxdist = max(maxdist, fabs(planes[w].dist));
7559         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7560         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7561         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7562         {
7563                 w = 0;
7564                 tempnumpoints = 4;
7565                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7566                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7567                 {
7568                         if (planenum2 == planenum)
7569                                 continue;
7570                         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);
7571                         w = !w;
7572                 }
7573                 if (tempnumpoints < 3)
7574                         continue;
7575                 // generate elements forming a triangle fan for this polygon
7576                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7577         }
7578 }
7579
7580 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)
7581 {
7582         texturelayer_t *layer;
7583         layer = t->currentlayers + t->currentnumlayers++;
7584         layer->type = type;
7585         layer->depthmask = depthmask;
7586         layer->blendfunc1 = blendfunc1;
7587         layer->blendfunc2 = blendfunc2;
7588         layer->texture = texture;
7589         layer->texmatrix = *matrix;
7590         layer->color[0] = r;
7591         layer->color[1] = g;
7592         layer->color[2] = b;
7593         layer->color[3] = a;
7594 }
7595
7596 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7597 {
7598         if(parms[0] == 0 && parms[1] == 0)
7599                 return false;
7600         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7601                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7602                         return false;
7603         return true;
7604 }
7605
7606 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7607 {
7608         double index, f;
7609         index = parms[2] + rsurface.shadertime * parms[3];
7610         index -= floor(index);
7611         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7612         {
7613         default:
7614         case Q3WAVEFUNC_NONE:
7615         case Q3WAVEFUNC_NOISE:
7616         case Q3WAVEFUNC_COUNT:
7617                 f = 0;
7618                 break;
7619         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7620         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7621         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7622         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7623         case Q3WAVEFUNC_TRIANGLE:
7624                 index *= 4;
7625                 f = index - floor(index);
7626                 if (index < 1)
7627                 {
7628                         // f = f;
7629                 }
7630                 else if (index < 2)
7631                         f = 1 - f;
7632                 else if (index < 3)
7633                         f = -f;
7634                 else
7635                         f = -(1 - f);
7636                 break;
7637         }
7638         f = parms[0] + parms[1] * f;
7639         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7640                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7641         return (float) f;
7642 }
7643
7644 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7645 {
7646         int w, h, idx;
7647         double f;
7648         double offsetd[2];
7649         float tcmat[12];
7650         matrix4x4_t matrix, temp;
7651         switch(tcmod->tcmod)
7652         {
7653                 case Q3TCMOD_COUNT:
7654                 case Q3TCMOD_NONE:
7655                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7656                                 matrix = r_waterscrollmatrix;
7657                         else
7658                                 matrix = identitymatrix;
7659                         break;
7660                 case Q3TCMOD_ENTITYTRANSLATE:
7661                         // this is used in Q3 to allow the gamecode to control texcoord
7662                         // scrolling on the entity, which is not supported in darkplaces yet.
7663                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7664                         break;
7665                 case Q3TCMOD_ROTATE:
7666                         f = tcmod->parms[0] * rsurface.shadertime;
7667                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7668                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7669                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7670                         break;
7671                 case Q3TCMOD_SCALE:
7672                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7673                         break;
7674                 case Q3TCMOD_SCROLL:
7675                         // extra care is needed because of precision breakdown with large values of time
7676                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7677                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7678                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7679                         break;
7680                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7681                         w = (int) tcmod->parms[0];
7682                         h = (int) tcmod->parms[1];
7683                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7684                         f = f - floor(f);
7685                         idx = (int) floor(f * w * h);
7686                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7687                         break;
7688                 case Q3TCMOD_STRETCH:
7689                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7690                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7691                         break;
7692                 case Q3TCMOD_TRANSFORM:
7693                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7694                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7695                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7696                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7697                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7698                         break;
7699                 case Q3TCMOD_TURBULENT:
7700                         // this is handled in the RSurf_PrepareVertices function
7701                         matrix = identitymatrix;
7702                         break;
7703         }
7704         temp = *texmatrix;
7705         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7706 }
7707
7708 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7709 {
7710         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7711         char name[MAX_QPATH];
7712         skinframe_t *skinframe;
7713         unsigned char pixels[296*194];
7714         strlcpy(cache->name, skinname, sizeof(cache->name));
7715         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7716         if (developer_loading.integer)
7717                 Con_Printf("loading %s\n", name);
7718         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7719         if (!skinframe || !skinframe->base)
7720         {
7721                 unsigned char *f;
7722                 fs_offset_t filesize;
7723                 skinframe = NULL;
7724                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7725                 if (f)
7726                 {
7727                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7728                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7729                         Mem_Free(f);
7730                 }
7731         }
7732         cache->skinframe = skinframe;
7733 }
7734
7735 texture_t *R_GetCurrentTexture(texture_t *t)
7736 {
7737         int i;
7738         const entity_render_t *ent = rsurface.entity;
7739         dp_model_t *model = ent->model;
7740         q3shaderinfo_layer_tcmod_t *tcmod;
7741
7742         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7743                 return t->currentframe;
7744         t->update_lastrenderframe = r_textureframe;
7745         t->update_lastrenderentity = (void *)ent;
7746
7747         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7748                 t->camera_entity = ent->entitynumber;
7749         else
7750                 t->camera_entity = 0;
7751
7752         // switch to an alternate material if this is a q1bsp animated material
7753         {
7754                 texture_t *texture = t;
7755                 int s = rsurface.ent_skinnum;
7756                 if ((unsigned int)s >= (unsigned int)model->numskins)
7757                         s = 0;
7758                 if (model->skinscenes)
7759                 {
7760                         if (model->skinscenes[s].framecount > 1)
7761                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7762                         else
7763                                 s = model->skinscenes[s].firstframe;
7764                 }
7765                 if (s > 0)
7766                         t = t + s * model->num_surfaces;
7767                 if (t->animated)
7768                 {
7769                         // use an alternate animation if the entity's frame is not 0,
7770                         // and only if the texture has an alternate animation
7771                         if (rsurface.ent_alttextures && t->anim_total[1])
7772                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7773                         else
7774                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7775                 }
7776                 texture->currentframe = t;
7777         }
7778
7779         // update currentskinframe to be a qw skin or animation frame
7780         if (rsurface.ent_qwskin >= 0)
7781         {
7782                 i = rsurface.ent_qwskin;
7783                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7784                 {
7785                         r_qwskincache_size = cl.maxclients;
7786                         if (r_qwskincache)
7787                                 Mem_Free(r_qwskincache);
7788                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7789                 }
7790                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7791                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7792                 t->currentskinframe = r_qwskincache[i].skinframe;
7793                 if (t->currentskinframe == NULL)
7794                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7795         }
7796         else if (t->numskinframes >= 2)
7797                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7798         if (t->backgroundnumskinframes >= 2)
7799                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7800
7801         t->currentmaterialflags = t->basematerialflags;
7802         t->currentalpha = rsurface.colormod[3];
7803         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7804                 t->currentalpha *= r_wateralpha.value;
7805         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7806                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7807         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7808                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7809         if (!(rsurface.ent_flags & RENDER_LIGHT))
7810                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7811         else if (FAKELIGHT_ENABLED)
7812         {
7813                 // no modellight if using fakelight for the map
7814         }
7815         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7816         {
7817                 // pick a model lighting mode
7818                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7819                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7820                 else
7821                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7822         }
7823         if (rsurface.ent_flags & RENDER_ADDITIVE)
7824                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7825         else if (t->currentalpha < 1)
7826                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7827         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7828         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7829                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7830         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7831                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7832         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7833                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7834         if (t->backgroundnumskinframes)
7835                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7836         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7837         {
7838                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7839                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7840         }
7841         else
7842                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7843         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7844         {
7845                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7846                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7847         }
7848         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7849                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7850
7851         // there is no tcmod
7852         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7853         {
7854                 t->currenttexmatrix = r_waterscrollmatrix;
7855                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7856         }
7857         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7858         {
7859                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7860                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7861         }
7862
7863         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7864                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7865         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7866                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7867
7868         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7869         if (t->currentskinframe->qpixels)
7870                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7871         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7872         if (!t->basetexture)
7873                 t->basetexture = r_texture_notexture;
7874         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7875         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7876         t->nmaptexture = t->currentskinframe->nmap;
7877         if (!t->nmaptexture)
7878                 t->nmaptexture = r_texture_blanknormalmap;
7879         t->glosstexture = r_texture_black;
7880         t->glowtexture = t->currentskinframe->glow;
7881         t->fogtexture = t->currentskinframe->fog;
7882         t->reflectmasktexture = t->currentskinframe->reflect;
7883         if (t->backgroundnumskinframes)
7884         {
7885                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7886                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7887                 t->backgroundglosstexture = r_texture_black;
7888                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7889                 if (!t->backgroundnmaptexture)
7890                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7891         }
7892         else
7893         {
7894                 t->backgroundbasetexture = r_texture_white;
7895                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7896                 t->backgroundglosstexture = r_texture_black;
7897                 t->backgroundglowtexture = NULL;
7898         }
7899         t->specularpower = r_shadow_glossexponent.value;
7900         // TODO: store reference values for these in the texture?
7901         t->specularscale = 0;
7902         if (r_shadow_gloss.integer > 0)
7903         {
7904                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7905                 {
7906                         if (r_shadow_glossintensity.value > 0)
7907                         {
7908                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7909                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7910                                 t->specularscale = r_shadow_glossintensity.value;
7911                         }
7912                 }
7913                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7914                 {
7915                         t->glosstexture = r_texture_white;
7916                         t->backgroundglosstexture = r_texture_white;
7917                         t->specularscale = r_shadow_gloss2intensity.value;
7918                         t->specularpower = r_shadow_gloss2exponent.value;
7919                 }
7920         }
7921         t->specularscale *= t->specularscalemod;
7922         t->specularpower *= t->specularpowermod;
7923         t->rtlightambient = 0;
7924
7925         // lightmaps mode looks bad with dlights using actual texturing, so turn
7926         // off the colormap and glossmap, but leave the normalmap on as it still
7927         // accurately represents the shading involved
7928         if (gl_lightmaps.integer)
7929         {
7930                 t->basetexture = r_texture_grey128;
7931                 t->pantstexture = r_texture_black;
7932                 t->shirttexture = r_texture_black;
7933                 t->nmaptexture = r_texture_blanknormalmap;
7934                 t->glosstexture = r_texture_black;
7935                 t->glowtexture = NULL;
7936                 t->fogtexture = NULL;
7937                 t->reflectmasktexture = NULL;
7938                 t->backgroundbasetexture = NULL;
7939                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7940                 t->backgroundglosstexture = r_texture_black;
7941                 t->backgroundglowtexture = NULL;
7942                 t->specularscale = 0;
7943                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7944         }
7945
7946         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7947         VectorClear(t->dlightcolor);
7948         t->currentnumlayers = 0;
7949         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7950         {
7951                 int blendfunc1, blendfunc2;
7952                 qboolean depthmask;
7953                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7954                 {
7955                         blendfunc1 = GL_SRC_ALPHA;
7956                         blendfunc2 = GL_ONE;
7957                 }
7958                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7959                 {
7960                         blendfunc1 = GL_SRC_ALPHA;
7961                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7962                 }
7963                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7964                 {
7965                         blendfunc1 = t->customblendfunc[0];
7966                         blendfunc2 = t->customblendfunc[1];
7967                 }
7968                 else
7969                 {
7970                         blendfunc1 = GL_ONE;
7971                         blendfunc2 = GL_ZERO;
7972                 }
7973                 // don't colormod evilblend textures
7974                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7975                         VectorSet(t->lightmapcolor, 1, 1, 1);
7976                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7977                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7978                 {
7979                         // fullbright is not affected by r_refdef.lightmapintensity
7980                         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]);
7981                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7982                                 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]);
7983                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7984                                 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]);
7985                 }
7986                 else
7987                 {
7988                         vec3_t ambientcolor;
7989                         float colorscale;
7990                         // set the color tint used for lights affecting this surface
7991                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7992                         colorscale = 2;
7993                         // q3bsp has no lightmap updates, so the lightstylevalue that
7994                         // would normally be baked into the lightmap must be
7995                         // applied to the color
7996                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7997                         if (model->type == mod_brushq3)
7998                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7999                         colorscale *= r_refdef.lightmapintensity;
8000                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8001                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8002                         // basic lit geometry
8003                         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]);
8004                         // add pants/shirt if needed
8005                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8006                                 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]);
8007                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8008                                 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]);
8009                         // now add ambient passes if needed
8010                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8011                         {
8012                                 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]);
8013                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8014                                         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]);
8015                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8016                                         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]);
8017                         }
8018                 }
8019                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8020                         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]);
8021                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8022                 {
8023                         // if this is opaque use alpha blend which will darken the earlier
8024                         // passes cheaply.
8025                         //
8026                         // if this is an alpha blended material, all the earlier passes
8027                         // were darkened by fog already, so we only need to add the fog
8028                         // color ontop through the fog mask texture
8029                         //
8030                         // if this is an additive blended material, all the earlier passes
8031                         // were darkened by fog already, and we should not add fog color
8032                         // (because the background was not darkened, there is no fog color
8033                         // that was lost behind it).
8034                         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]);
8035                 }
8036         }
8037
8038         return t->currentframe;
8039 }
8040
8041 rsurfacestate_t rsurface;
8042
8043 void RSurf_ActiveWorldEntity(void)
8044 {
8045         dp_model_t *model = r_refdef.scene.worldmodel;
8046         //if (rsurface.entity == r_refdef.scene.worldentity)
8047         //      return;
8048         rsurface.entity = r_refdef.scene.worldentity;
8049         rsurface.skeleton = NULL;
8050         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8051         rsurface.ent_skinnum = 0;
8052         rsurface.ent_qwskin = -1;
8053         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8054         rsurface.shadertime = r_refdef.scene.time;
8055         rsurface.matrix = identitymatrix;
8056         rsurface.inversematrix = identitymatrix;
8057         rsurface.matrixscale = 1;
8058         rsurface.inversematrixscale = 1;
8059         R_EntityMatrix(&identitymatrix);
8060         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8061         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8062         rsurface.fograngerecip = r_refdef.fograngerecip;
8063         rsurface.fogheightfade = r_refdef.fogheightfade;
8064         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8065         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8066         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8067         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8068         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8069         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8070         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8071         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8072         rsurface.colormod[3] = 1;
8073         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);
8074         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8075         rsurface.frameblend[0].lerp = 1;
8076         rsurface.ent_alttextures = false;
8077         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8078         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8079         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8080         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8081         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8082         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8083         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8084         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8085         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8086         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8087         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8088         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8089         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8090         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8091         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8092         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8093         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8094         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8095         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8096         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8097         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8098         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8099         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8100         rsurface.modelelement3i = model->surfmesh.data_element3i;
8101         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8102         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8103         rsurface.modelelement3s = model->surfmesh.data_element3s;
8104         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8105         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8106         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8107         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8108         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8109         rsurface.modelsurfaces = model->data_surfaces;
8110         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8111         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8112         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8113         rsurface.modelgeneratedvertex = false;
8114         rsurface.batchgeneratedvertex = false;
8115         rsurface.batchfirstvertex = 0;
8116         rsurface.batchnumvertices = 0;
8117         rsurface.batchfirsttriangle = 0;
8118         rsurface.batchnumtriangles = 0;
8119         rsurface.batchvertex3f  = NULL;
8120         rsurface.batchvertex3f_vertexbuffer = NULL;
8121         rsurface.batchvertex3f_bufferoffset = 0;
8122         rsurface.batchsvector3f = NULL;
8123         rsurface.batchsvector3f_vertexbuffer = NULL;
8124         rsurface.batchsvector3f_bufferoffset = 0;
8125         rsurface.batchtvector3f = NULL;
8126         rsurface.batchtvector3f_vertexbuffer = NULL;
8127         rsurface.batchtvector3f_bufferoffset = 0;
8128         rsurface.batchnormal3f  = NULL;
8129         rsurface.batchnormal3f_vertexbuffer = NULL;
8130         rsurface.batchnormal3f_bufferoffset = 0;
8131         rsurface.batchlightmapcolor4f = NULL;
8132         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8133         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8134         rsurface.batchtexcoordtexture2f = NULL;
8135         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8136         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8137         rsurface.batchtexcoordlightmap2f = NULL;
8138         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8139         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8140         rsurface.batchvertexmesh = NULL;
8141         rsurface.batchvertexmeshbuffer = NULL;
8142         rsurface.batchvertex3fbuffer = NULL;
8143         rsurface.batchelement3i = NULL;
8144         rsurface.batchelement3i_indexbuffer = NULL;
8145         rsurface.batchelement3i_bufferoffset = 0;
8146         rsurface.batchelement3s = NULL;
8147         rsurface.batchelement3s_indexbuffer = NULL;
8148         rsurface.batchelement3s_bufferoffset = 0;
8149         rsurface.passcolor4f = NULL;
8150         rsurface.passcolor4f_vertexbuffer = NULL;
8151         rsurface.passcolor4f_bufferoffset = 0;
8152 }
8153
8154 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8155 {
8156         dp_model_t *model = ent->model;
8157         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8158         //      return;
8159         rsurface.entity = (entity_render_t *)ent;
8160         rsurface.skeleton = ent->skeleton;
8161         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8162         rsurface.ent_skinnum = ent->skinnum;
8163         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;
8164         rsurface.ent_flags = ent->flags;
8165         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8166         rsurface.matrix = ent->matrix;
8167         rsurface.inversematrix = ent->inversematrix;
8168         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8169         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8170         R_EntityMatrix(&rsurface.matrix);
8171         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8172         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8173         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8174         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8175         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8176         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8177         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8178         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8179         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8180         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8181         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8182         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8183         rsurface.colormod[3] = ent->alpha;
8184         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8185         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8186         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8187         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8188         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8189         if (ent->model->brush.submodel && !prepass)
8190         {
8191                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8192                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8193         }
8194         if (model->surfmesh.isanimated && model->AnimateVertices)
8195         {
8196                 if (ent->animcache_vertex3f)
8197                 {
8198                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8199                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8200                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8201                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8202                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8203                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8204                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8205                 }
8206                 else if (wanttangents)
8207                 {
8208                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8209                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8211                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8212                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8213                         rsurface.modelvertexmesh = NULL;
8214                         rsurface.modelvertexmeshbuffer = NULL;
8215                         rsurface.modelvertex3fbuffer = NULL;
8216                 }
8217                 else if (wantnormals)
8218                 {
8219                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8220                         rsurface.modelsvector3f = NULL;
8221                         rsurface.modeltvector3f = NULL;
8222                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8223                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8224                         rsurface.modelvertexmesh = NULL;
8225                         rsurface.modelvertexmeshbuffer = NULL;
8226                         rsurface.modelvertex3fbuffer = NULL;
8227                 }
8228                 else
8229                 {
8230                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8231                         rsurface.modelsvector3f = NULL;
8232                         rsurface.modeltvector3f = NULL;
8233                         rsurface.modelnormal3f = NULL;
8234                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8235                         rsurface.modelvertexmesh = NULL;
8236                         rsurface.modelvertexmeshbuffer = NULL;
8237                         rsurface.modelvertex3fbuffer = NULL;
8238                 }
8239                 rsurface.modelvertex3f_vertexbuffer = 0;
8240                 rsurface.modelvertex3f_bufferoffset = 0;
8241                 rsurface.modelsvector3f_vertexbuffer = 0;
8242                 rsurface.modelsvector3f_bufferoffset = 0;
8243                 rsurface.modeltvector3f_vertexbuffer = 0;
8244                 rsurface.modeltvector3f_bufferoffset = 0;
8245                 rsurface.modelnormal3f_vertexbuffer = 0;
8246                 rsurface.modelnormal3f_bufferoffset = 0;
8247                 rsurface.modelgeneratedvertex = true;
8248         }
8249         else
8250         {
8251                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8252                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8253                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8254                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8255                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8257                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8258                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8260                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8261                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8262                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8263                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8264                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8265                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8266                 rsurface.modelgeneratedvertex = false;
8267         }
8268         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8269         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8270         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8271         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8272         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8274         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8275         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8277         rsurface.modelelement3i = model->surfmesh.data_element3i;
8278         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8279         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8280         rsurface.modelelement3s = model->surfmesh.data_element3s;
8281         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8282         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8283         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8284         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8285         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8286         rsurface.modelsurfaces = model->data_surfaces;
8287         rsurface.batchgeneratedvertex = false;
8288         rsurface.batchfirstvertex = 0;
8289         rsurface.batchnumvertices = 0;
8290         rsurface.batchfirsttriangle = 0;
8291         rsurface.batchnumtriangles = 0;
8292         rsurface.batchvertex3f  = NULL;
8293         rsurface.batchvertex3f_vertexbuffer = NULL;
8294         rsurface.batchvertex3f_bufferoffset = 0;
8295         rsurface.batchsvector3f = NULL;
8296         rsurface.batchsvector3f_vertexbuffer = NULL;
8297         rsurface.batchsvector3f_bufferoffset = 0;
8298         rsurface.batchtvector3f = NULL;
8299         rsurface.batchtvector3f_vertexbuffer = NULL;
8300         rsurface.batchtvector3f_bufferoffset = 0;
8301         rsurface.batchnormal3f  = NULL;
8302         rsurface.batchnormal3f_vertexbuffer = NULL;
8303         rsurface.batchnormal3f_bufferoffset = 0;
8304         rsurface.batchlightmapcolor4f = NULL;
8305         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8306         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8307         rsurface.batchtexcoordtexture2f = NULL;
8308         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8309         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8310         rsurface.batchtexcoordlightmap2f = NULL;
8311         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8312         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8313         rsurface.batchvertexmesh = NULL;
8314         rsurface.batchvertexmeshbuffer = NULL;
8315         rsurface.batchvertex3fbuffer = NULL;
8316         rsurface.batchelement3i = NULL;
8317         rsurface.batchelement3i_indexbuffer = NULL;
8318         rsurface.batchelement3i_bufferoffset = 0;
8319         rsurface.batchelement3s = NULL;
8320         rsurface.batchelement3s_indexbuffer = NULL;
8321         rsurface.batchelement3s_bufferoffset = 0;
8322         rsurface.passcolor4f = NULL;
8323         rsurface.passcolor4f_vertexbuffer = NULL;
8324         rsurface.passcolor4f_bufferoffset = 0;
8325 }
8326
8327 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)
8328 {
8329         rsurface.entity = r_refdef.scene.worldentity;
8330         rsurface.skeleton = NULL;
8331         rsurface.ent_skinnum = 0;
8332         rsurface.ent_qwskin = -1;
8333         rsurface.ent_flags = entflags;
8334         rsurface.shadertime = r_refdef.scene.time - shadertime;
8335         rsurface.modelnumvertices = numvertices;
8336         rsurface.modelnumtriangles = numtriangles;
8337         rsurface.matrix = *matrix;
8338         rsurface.inversematrix = *inversematrix;
8339         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8340         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8341         R_EntityMatrix(&rsurface.matrix);
8342         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8343         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8344         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8345         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8346         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8347         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8348         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8349         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8350         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8351         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8352         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8353         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8354         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);
8355         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8356         rsurface.frameblend[0].lerp = 1;
8357         rsurface.ent_alttextures = false;
8358         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8359         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8360         if (wanttangents)
8361         {
8362                 rsurface.modelvertex3f = (float *)vertex3f;
8363                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8364                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8365                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8366         }
8367         else if (wantnormals)
8368         {
8369                 rsurface.modelvertex3f = (float *)vertex3f;
8370                 rsurface.modelsvector3f = NULL;
8371                 rsurface.modeltvector3f = NULL;
8372                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8373         }
8374         else
8375         {
8376                 rsurface.modelvertex3f = (float *)vertex3f;
8377                 rsurface.modelsvector3f = NULL;
8378                 rsurface.modeltvector3f = NULL;
8379                 rsurface.modelnormal3f = NULL;
8380         }
8381         rsurface.modelvertexmesh = NULL;
8382         rsurface.modelvertexmeshbuffer = NULL;
8383         rsurface.modelvertex3fbuffer = NULL;
8384         rsurface.modelvertex3f_vertexbuffer = 0;
8385         rsurface.modelvertex3f_bufferoffset = 0;
8386         rsurface.modelsvector3f_vertexbuffer = 0;
8387         rsurface.modelsvector3f_bufferoffset = 0;
8388         rsurface.modeltvector3f_vertexbuffer = 0;
8389         rsurface.modeltvector3f_bufferoffset = 0;
8390         rsurface.modelnormal3f_vertexbuffer = 0;
8391         rsurface.modelnormal3f_bufferoffset = 0;
8392         rsurface.modelgeneratedvertex = true;
8393         rsurface.modellightmapcolor4f  = (float *)color4f;
8394         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8395         rsurface.modellightmapcolor4f_bufferoffset = 0;
8396         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8397         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8398         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8399         rsurface.modeltexcoordlightmap2f  = NULL;
8400         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8401         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8402         rsurface.modelelement3i = (int *)element3i;
8403         rsurface.modelelement3i_indexbuffer = NULL;
8404         rsurface.modelelement3i_bufferoffset = 0;
8405         rsurface.modelelement3s = (unsigned short *)element3s;
8406         rsurface.modelelement3s_indexbuffer = NULL;
8407         rsurface.modelelement3s_bufferoffset = 0;
8408         rsurface.modellightmapoffsets = NULL;
8409         rsurface.modelsurfaces = NULL;
8410         rsurface.batchgeneratedvertex = false;
8411         rsurface.batchfirstvertex = 0;
8412         rsurface.batchnumvertices = 0;
8413         rsurface.batchfirsttriangle = 0;
8414         rsurface.batchnumtriangles = 0;
8415         rsurface.batchvertex3f  = NULL;
8416         rsurface.batchvertex3f_vertexbuffer = NULL;
8417         rsurface.batchvertex3f_bufferoffset = 0;
8418         rsurface.batchsvector3f = NULL;
8419         rsurface.batchsvector3f_vertexbuffer = NULL;
8420         rsurface.batchsvector3f_bufferoffset = 0;
8421         rsurface.batchtvector3f = NULL;
8422         rsurface.batchtvector3f_vertexbuffer = NULL;
8423         rsurface.batchtvector3f_bufferoffset = 0;
8424         rsurface.batchnormal3f  = NULL;
8425         rsurface.batchnormal3f_vertexbuffer = NULL;
8426         rsurface.batchnormal3f_bufferoffset = 0;
8427         rsurface.batchlightmapcolor4f = NULL;
8428         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8429         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8430         rsurface.batchtexcoordtexture2f = NULL;
8431         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8432         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8433         rsurface.batchtexcoordlightmap2f = NULL;
8434         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8435         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8436         rsurface.batchvertexmesh = NULL;
8437         rsurface.batchvertexmeshbuffer = NULL;
8438         rsurface.batchvertex3fbuffer = NULL;
8439         rsurface.batchelement3i = NULL;
8440         rsurface.batchelement3i_indexbuffer = NULL;
8441         rsurface.batchelement3i_bufferoffset = 0;
8442         rsurface.batchelement3s = NULL;
8443         rsurface.batchelement3s_indexbuffer = NULL;
8444         rsurface.batchelement3s_bufferoffset = 0;
8445         rsurface.passcolor4f = NULL;
8446         rsurface.passcolor4f_vertexbuffer = NULL;
8447         rsurface.passcolor4f_bufferoffset = 0;
8448
8449         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8450         {
8451                 if ((wantnormals || wanttangents) && !normal3f)
8452                 {
8453                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8454                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8455                 }
8456                 if (wanttangents && !svector3f)
8457                 {
8458                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8459                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8460                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8461                 }
8462         }
8463 }
8464
8465 float RSurf_FogPoint(const float *v)
8466 {
8467         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8468         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8469         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8470         float FogHeightFade = r_refdef.fogheightfade;
8471         float fogfrac;
8472         unsigned int fogmasktableindex;
8473         if (r_refdef.fogplaneviewabove)
8474                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8475         else
8476                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8477         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8478         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8479 }
8480
8481 float RSurf_FogVertex(const float *v)
8482 {
8483         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8484         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8485         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8486         float FogHeightFade = rsurface.fogheightfade;
8487         float fogfrac;
8488         unsigned int fogmasktableindex;
8489         if (r_refdef.fogplaneviewabove)
8490                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8491         else
8492                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8493         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8494         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8495 }
8496
8497 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8498 {
8499         int i;
8500         for (i = 0;i < numelements;i++)
8501                 outelement3i[i] = inelement3i[i] + adjust;
8502 }
8503
8504 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8505 extern cvar_t gl_vbo;
8506 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8507 {
8508         int deformindex;
8509         int firsttriangle;
8510         int numtriangles;
8511         int firstvertex;
8512         int endvertex;
8513         int numvertices;
8514         int surfacefirsttriangle;
8515         int surfacenumtriangles;
8516         int surfacefirstvertex;
8517         int surfaceendvertex;
8518         int surfacenumvertices;
8519         int batchnumvertices;
8520         int batchnumtriangles;
8521         int needsupdate;
8522         int i, j;
8523         qboolean gaps;
8524         qboolean dynamicvertex;
8525         float amplitude;
8526         float animpos;
8527         float scale;
8528         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8529         float waveparms[4];
8530         q3shaderinfo_deform_t *deform;
8531         const msurface_t *surface, *firstsurface;
8532         r_vertexmesh_t *vertexmesh;
8533         if (!texturenumsurfaces)
8534                 return;
8535         // find vertex range of this surface batch
8536         gaps = false;
8537         firstsurface = texturesurfacelist[0];
8538         firsttriangle = firstsurface->num_firsttriangle;
8539         batchnumvertices = 0;
8540         batchnumtriangles = 0;
8541         firstvertex = endvertex = firstsurface->num_firstvertex;
8542         for (i = 0;i < texturenumsurfaces;i++)
8543         {
8544                 surface = texturesurfacelist[i];
8545                 if (surface != firstsurface + i)
8546                         gaps = true;
8547                 surfacefirstvertex = surface->num_firstvertex;
8548                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8549                 surfacenumvertices = surface->num_vertices;
8550                 surfacenumtriangles = surface->num_triangles;
8551                 if (firstvertex > surfacefirstvertex)
8552                         firstvertex = surfacefirstvertex;
8553                 if (endvertex < surfaceendvertex)
8554                         endvertex = surfaceendvertex;
8555                 batchnumvertices += surfacenumvertices;
8556                 batchnumtriangles += surfacenumtriangles;
8557         }
8558
8559         // we now know the vertex range used, and if there are any gaps in it
8560         rsurface.batchfirstvertex = firstvertex;
8561         rsurface.batchnumvertices = endvertex - firstvertex;
8562         rsurface.batchfirsttriangle = firsttriangle;
8563         rsurface.batchnumtriangles = batchnumtriangles;
8564
8565         // this variable holds flags for which properties have been updated that
8566         // may require regenerating vertexmesh array...
8567         needsupdate = 0;
8568
8569         // check if any dynamic vertex processing must occur
8570         dynamicvertex = false;
8571
8572         // if there is a chance of animated vertex colors, it's a dynamic batch
8573         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8574         {
8575                 dynamicvertex = true;
8576                 batchneed |= BATCHNEED_NOGAPS;
8577                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8578         }
8579
8580         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8581         {
8582                 switch (deform->deform)
8583                 {
8584                 default:
8585                 case Q3DEFORM_PROJECTIONSHADOW:
8586                 case Q3DEFORM_TEXT0:
8587                 case Q3DEFORM_TEXT1:
8588                 case Q3DEFORM_TEXT2:
8589                 case Q3DEFORM_TEXT3:
8590                 case Q3DEFORM_TEXT4:
8591                 case Q3DEFORM_TEXT5:
8592                 case Q3DEFORM_TEXT6:
8593                 case Q3DEFORM_TEXT7:
8594                 case Q3DEFORM_NONE:
8595                         break;
8596                 case Q3DEFORM_AUTOSPRITE:
8597                         dynamicvertex = true;
8598                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8599                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8600                         break;
8601                 case Q3DEFORM_AUTOSPRITE2:
8602                         dynamicvertex = true;
8603                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8604                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8605                         break;
8606                 case Q3DEFORM_NORMAL:
8607                         dynamicvertex = true;
8608                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8609                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8610                         break;
8611                 case Q3DEFORM_WAVE:
8612                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8613                                 break; // if wavefunc is a nop, ignore this transform
8614                         dynamicvertex = true;
8615                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8616                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8617                         break;
8618                 case Q3DEFORM_BULGE:
8619                         dynamicvertex = true;
8620                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8621                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8622                         break;
8623                 case Q3DEFORM_MOVE:
8624                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8625                                 break; // if wavefunc is a nop, ignore this transform
8626                         dynamicvertex = true;
8627                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8628                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8629                         break;
8630                 }
8631         }
8632         switch(rsurface.texture->tcgen.tcgen)
8633         {
8634         default:
8635         case Q3TCGEN_TEXTURE:
8636                 break;
8637         case Q3TCGEN_LIGHTMAP:
8638                 dynamicvertex = true;
8639                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8640                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8641                 break;
8642         case Q3TCGEN_VECTOR:
8643                 dynamicvertex = true;
8644                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8645                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8646                 break;
8647         case Q3TCGEN_ENVIRONMENT:
8648                 dynamicvertex = true;
8649                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8650                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8651                 break;
8652         }
8653         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8654         {
8655                 dynamicvertex = true;
8656                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8657                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8658         }
8659
8660         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8661         {
8662                 dynamicvertex = true;
8663                 batchneed |= BATCHNEED_NOGAPS;
8664                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8665         }
8666
8667         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8668         {
8669                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8670                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8671                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8672                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8673                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8674                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8675                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8676         }
8677
8678         // when the model data has no vertex buffer (dynamic mesh), we need to
8679         // eliminate gaps
8680         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8681                 batchneed |= BATCHNEED_NOGAPS;
8682
8683         // if needsupdate, we have to do a dynamic vertex batch for sure
8684         if (needsupdate & batchneed)
8685                 dynamicvertex = true;
8686
8687         // see if we need to build vertexmesh from arrays
8688         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8689                 dynamicvertex = true;
8690
8691         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8692         // also some drivers strongly dislike firstvertex
8693         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8694                 dynamicvertex = true;
8695
8696         rsurface.batchvertex3f = rsurface.modelvertex3f;
8697         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8698         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8699         rsurface.batchsvector3f = rsurface.modelsvector3f;
8700         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8701         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8702         rsurface.batchtvector3f = rsurface.modeltvector3f;
8703         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8704         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8705         rsurface.batchnormal3f = rsurface.modelnormal3f;
8706         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8707         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8708         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8709         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8710         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8711         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8712         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8713         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8714         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8715         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8716         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8717         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8718         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8719         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8720         rsurface.batchelement3i = rsurface.modelelement3i;
8721         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8722         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8723         rsurface.batchelement3s = rsurface.modelelement3s;
8724         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8725         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8726
8727         // if any dynamic vertex processing has to occur in software, we copy the
8728         // entire surface list together before processing to rebase the vertices
8729         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8730         //
8731         // if any gaps exist and we do not have a static vertex buffer, we have to
8732         // copy the surface list together to avoid wasting upload bandwidth on the
8733         // vertices in the gaps.
8734         //
8735         // if gaps exist and we have a static vertex buffer, we still have to
8736         // combine the index buffer ranges into one dynamic index buffer.
8737         //
8738         // in all cases we end up with data that can be drawn in one call.
8739
8740         if (!dynamicvertex)
8741         {
8742                 // static vertex data, just set pointers...
8743                 rsurface.batchgeneratedvertex = false;
8744                 // if there are gaps, we want to build a combined index buffer,
8745                 // otherwise use the original static buffer with an appropriate offset
8746                 if (gaps)
8747                 {
8748                         // build a new triangle elements array for this batch
8749                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8750                         rsurface.batchfirsttriangle = 0;
8751                         numtriangles = 0;
8752                         for (i = 0;i < texturenumsurfaces;i++)
8753                         {
8754                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8755                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8756                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8757                                 numtriangles += surfacenumtriangles;
8758                         }
8759                         rsurface.batchelement3i_indexbuffer = NULL;
8760                         rsurface.batchelement3i_bufferoffset = 0;
8761                         rsurface.batchelement3s = NULL;
8762                         rsurface.batchelement3s_indexbuffer = NULL;
8763                         rsurface.batchelement3s_bufferoffset = 0;
8764                         if (endvertex <= 65536)
8765                         {
8766                                 // make a 16bit (unsigned short) index array if possible
8767                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8768                                 for (i = 0;i < numtriangles*3;i++)
8769                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8770                         }
8771                 }
8772                 return;
8773         }
8774
8775         // something needs software processing, do it for real...
8776         // we only directly handle separate array data in this case and then
8777         // generate interleaved data if needed...
8778         rsurface.batchgeneratedvertex = true;
8779
8780         // now copy the vertex data into a combined array and make an index array
8781         // (this is what Quake3 does all the time)
8782         //if (gaps || rsurface.batchfirstvertex)
8783         {
8784                 rsurface.batchvertex3fbuffer = NULL;
8785                 rsurface.batchvertexmesh = NULL;
8786                 rsurface.batchvertexmeshbuffer = NULL;
8787                 rsurface.batchvertex3f = NULL;
8788                 rsurface.batchvertex3f_vertexbuffer = NULL;
8789                 rsurface.batchvertex3f_bufferoffset = 0;
8790                 rsurface.batchsvector3f = NULL;
8791                 rsurface.batchsvector3f_vertexbuffer = NULL;
8792                 rsurface.batchsvector3f_bufferoffset = 0;
8793                 rsurface.batchtvector3f = NULL;
8794                 rsurface.batchtvector3f_vertexbuffer = NULL;
8795                 rsurface.batchtvector3f_bufferoffset = 0;
8796                 rsurface.batchnormal3f = NULL;
8797                 rsurface.batchnormal3f_vertexbuffer = NULL;
8798                 rsurface.batchnormal3f_bufferoffset = 0;
8799                 rsurface.batchlightmapcolor4f = NULL;
8800                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8801                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8802                 rsurface.batchtexcoordtexture2f = NULL;
8803                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8804                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8805                 rsurface.batchtexcoordlightmap2f = NULL;
8806                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8807                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8808                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8809                 rsurface.batchelement3i_indexbuffer = NULL;
8810                 rsurface.batchelement3i_bufferoffset = 0;
8811                 rsurface.batchelement3s = NULL;
8812                 rsurface.batchelement3s_indexbuffer = NULL;
8813                 rsurface.batchelement3s_bufferoffset = 0;
8814                 // we'll only be setting up certain arrays as needed
8815                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8816                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8817                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8818                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8820                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8822                 {
8823                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8824                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8825                 }
8826                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8827                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8828                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8829                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8830                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8831                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8832                 numvertices = 0;
8833                 numtriangles = 0;
8834                 for (i = 0;i < texturenumsurfaces;i++)
8835                 {
8836                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8837                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8838                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8839                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8840                         // copy only the data requested
8841                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8842                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8843                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8844                         {
8845                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8846                                 {
8847                                         if (rsurface.batchvertex3f)
8848                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8849                                         else
8850                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8851                                 }
8852                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8853                                 {
8854                                         if (rsurface.modelnormal3f)
8855                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8856                                         else
8857                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8858                                 }
8859                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8860                                 {
8861                                         if (rsurface.modelsvector3f)
8862                                         {
8863                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8864                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8865                                         }
8866                                         else
8867                                         {
8868                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8869                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8870                                         }
8871                                 }
8872                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8873                                 {
8874                                         if (rsurface.modellightmapcolor4f)
8875                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8876                                         else
8877                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8878                                 }
8879                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8880                                 {
8881                                         if (rsurface.modeltexcoordtexture2f)
8882                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8883                                         else
8884                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8885                                 }
8886                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8887                                 {
8888                                         if (rsurface.modeltexcoordlightmap2f)
8889                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8890                                         else
8891                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8892                                 }
8893                         }
8894                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8895                         numvertices += surfacenumvertices;
8896                         numtriangles += surfacenumtriangles;
8897                 }
8898
8899                 // generate a 16bit index array as well if possible
8900                 // (in general, dynamic batches fit)
8901                 if (numvertices <= 65536)
8902                 {
8903                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8904                         for (i = 0;i < numtriangles*3;i++)
8905                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8906                 }
8907
8908                 // since we've copied everything, the batch now starts at 0
8909                 rsurface.batchfirstvertex = 0;
8910                 rsurface.batchnumvertices = batchnumvertices;
8911                 rsurface.batchfirsttriangle = 0;
8912                 rsurface.batchnumtriangles = batchnumtriangles;
8913         }
8914
8915         // q1bsp surfaces rendered in vertex color mode have to have colors
8916         // calculated based on lightstyles
8917         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8918         {
8919                 // generate color arrays for the surfaces in this list
8920                 int c[4];
8921                 int scale;
8922                 int size3;
8923                 const int *offsets;
8924                 const unsigned char *lm;
8925                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8926                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8927                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8928                 numvertices = 0;
8929                 for (i = 0;i < texturenumsurfaces;i++)
8930                 {
8931                         surface = texturesurfacelist[i];
8932                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8933                         surfacenumvertices = surface->num_vertices;
8934                         if (surface->lightmapinfo->samples)
8935                         {
8936                                 for (j = 0;j < surfacenumvertices;j++)
8937                                 {
8938                                         lm = surface->lightmapinfo->samples + offsets[j];
8939                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8940                                         VectorScale(lm, scale, c);
8941                                         if (surface->lightmapinfo->styles[1] != 255)
8942                                         {
8943                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8944                                                 lm += size3;
8945                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8946                                                 VectorMA(c, scale, lm, c);
8947                                                 if (surface->lightmapinfo->styles[2] != 255)
8948                                                 {
8949                                                         lm += size3;
8950                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8951                                                         VectorMA(c, scale, lm, c);
8952                                                         if (surface->lightmapinfo->styles[3] != 255)
8953                                                         {
8954                                                                 lm += size3;
8955                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8956                                                                 VectorMA(c, scale, lm, c);
8957                                                         }
8958                                                 }
8959                                         }
8960                                         c[0] >>= 7;
8961                                         c[1] >>= 7;
8962                                         c[2] >>= 7;
8963                                         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);
8964                                         numvertices++;
8965                                 }
8966                         }
8967                         else
8968                         {
8969                                 for (j = 0;j < surfacenumvertices;j++)
8970                                 {
8971                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8972                                         numvertices++;
8973                                 }
8974                         }
8975                 }
8976         }
8977
8978         // if vertices are deformed (sprite flares and things in maps, possibly
8979         // water waves, bulges and other deformations), modify the copied vertices
8980         // in place
8981         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8982         {
8983                 switch (deform->deform)
8984                 {
8985                 default:
8986                 case Q3DEFORM_PROJECTIONSHADOW:
8987                 case Q3DEFORM_TEXT0:
8988                 case Q3DEFORM_TEXT1:
8989                 case Q3DEFORM_TEXT2:
8990                 case Q3DEFORM_TEXT3:
8991                 case Q3DEFORM_TEXT4:
8992                 case Q3DEFORM_TEXT5:
8993                 case Q3DEFORM_TEXT6:
8994                 case Q3DEFORM_TEXT7:
8995                 case Q3DEFORM_NONE:
8996                         break;
8997                 case Q3DEFORM_AUTOSPRITE:
8998                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8999                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9000                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9001                         VectorNormalize(newforward);
9002                         VectorNormalize(newright);
9003                         VectorNormalize(newup);
9004 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9005 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9006 //                      rsurface.batchvertex3f_bufferoffset = 0;
9007 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9008 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9009 //                      rsurface.batchsvector3f_bufferoffset = 0;
9010 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9011 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9012 //                      rsurface.batchtvector3f_bufferoffset = 0;
9013 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9014 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9015 //                      rsurface.batchnormal3f_bufferoffset = 0;
9016                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9017                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9018                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9019                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9020                                 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);
9021                         // a single autosprite surface can contain multiple sprites...
9022                         for (j = 0;j < batchnumvertices - 3;j += 4)
9023                         {
9024                                 VectorClear(center);
9025                                 for (i = 0;i < 4;i++)
9026                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9027                                 VectorScale(center, 0.25f, center);
9028                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9029                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9030                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9031                                 for (i = 0;i < 4;i++)
9032                                 {
9033                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9034                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9035                                 }
9036                         }
9037                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9038                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9039                         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);
9040                         break;
9041                 case Q3DEFORM_AUTOSPRITE2:
9042                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9043                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9044                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9045                         VectorNormalize(newforward);
9046                         VectorNormalize(newright);
9047                         VectorNormalize(newup);
9048 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9049 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9050 //                      rsurface.batchvertex3f_bufferoffset = 0;
9051                         {
9052                                 const float *v1, *v2;
9053                                 vec3_t start, end;
9054                                 float f, l;
9055                                 struct
9056                                 {
9057                                         float length2;
9058                                         const float *v1;
9059                                         const float *v2;
9060                                 }
9061                                 shortest[2];
9062                                 memset(shortest, 0, sizeof(shortest));
9063                                 // a single autosprite surface can contain multiple sprites...
9064                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9065                                 {
9066                                         VectorClear(center);
9067                                         for (i = 0;i < 4;i++)
9068                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9069                                         VectorScale(center, 0.25f, center);
9070                                         // find the two shortest edges, then use them to define the
9071                                         // axis vectors for rotating around the central axis
9072                                         for (i = 0;i < 6;i++)
9073                                         {
9074                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9075                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9076                                                 l = VectorDistance2(v1, v2);
9077                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9078                                                 if (v1[2] != v2[2])
9079                                                         l += (1.0f / 1024.0f);
9080                                                 if (shortest[0].length2 > l || i == 0)
9081                                                 {
9082                                                         shortest[1] = shortest[0];
9083                                                         shortest[0].length2 = l;
9084                                                         shortest[0].v1 = v1;
9085                                                         shortest[0].v2 = v2;
9086                                                 }
9087                                                 else if (shortest[1].length2 > l || i == 1)
9088                                                 {
9089                                                         shortest[1].length2 = l;
9090                                                         shortest[1].v1 = v1;
9091                                                         shortest[1].v2 = v2;
9092                                                 }
9093                                         }
9094                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9095                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9096                                         // this calculates the right vector from the shortest edge
9097                                         // and the up vector from the edge midpoints
9098                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9099                                         VectorNormalize(right);
9100                                         VectorSubtract(end, start, up);
9101                                         VectorNormalize(up);
9102                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9103                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9104                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9105                                         VectorNegate(forward, forward);
9106                                         VectorReflect(forward, 0, up, forward);
9107                                         VectorNormalize(forward);
9108                                         CrossProduct(up, forward, newright);
9109                                         VectorNormalize(newright);
9110                                         // rotate the quad around the up axis vector, this is made
9111                                         // especially easy by the fact we know the quad is flat,
9112                                         // so we only have to subtract the center position and
9113                                         // measure distance along the right vector, and then
9114                                         // multiply that by the newright vector and add back the
9115                                         // center position
9116                                         // we also need to subtract the old position to undo the
9117                                         // displacement from the center, which we do with a
9118                                         // DotProduct, the subtraction/addition of center is also
9119                                         // optimized into DotProducts here
9120                                         l = DotProduct(right, center);
9121                                         for (i = 0;i < 4;i++)
9122                                         {
9123                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9124                                                 f = DotProduct(right, v1) - l;
9125                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9126                                         }
9127                                 }
9128                         }
9129                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9130                         {
9131 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9132 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9133 //                              rsurface.batchnormal3f_bufferoffset = 0;
9134                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9135                         }
9136                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9137                         {
9138 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9139 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9140 //                              rsurface.batchsvector3f_bufferoffset = 0;
9141 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9142 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9143 //                              rsurface.batchtvector3f_bufferoffset = 0;
9144                                 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);
9145                         }
9146                         break;
9147                 case Q3DEFORM_NORMAL:
9148                         // deform the normals to make reflections wavey
9149                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9150                         rsurface.batchnormal3f_vertexbuffer = NULL;
9151                         rsurface.batchnormal3f_bufferoffset = 0;
9152                         for (j = 0;j < batchnumvertices;j++)
9153                         {
9154                                 float vertex[3];
9155                                 float *normal = rsurface.batchnormal3f + 3*j;
9156                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9157                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9158                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9159                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9160                                 VectorNormalize(normal);
9161                         }
9162                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9163                         {
9164 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9165 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9166 //                              rsurface.batchsvector3f_bufferoffset = 0;
9167 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchtvector3f_bufferoffset = 0;
9170                                 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);
9171                         }
9172                         break;
9173                 case Q3DEFORM_WAVE:
9174                         // deform vertex array to make wavey water and flags and such
9175                         waveparms[0] = deform->waveparms[0];
9176                         waveparms[1] = deform->waveparms[1];
9177                         waveparms[2] = deform->waveparms[2];
9178                         waveparms[3] = deform->waveparms[3];
9179                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9180                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9181                         // this is how a divisor of vertex influence on deformation
9182                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9183                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9184 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9185 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9186 //                      rsurface.batchvertex3f_bufferoffset = 0;
9187 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9188 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9189 //                      rsurface.batchnormal3f_bufferoffset = 0;
9190                         for (j = 0;j < batchnumvertices;j++)
9191                         {
9192                                 // if the wavefunc depends on time, evaluate it per-vertex
9193                                 if (waveparms[3])
9194                                 {
9195                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9196                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9197                                 }
9198                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9199                         }
9200                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9201                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9202                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9203                         {
9204 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9205 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9206 //                              rsurface.batchsvector3f_bufferoffset = 0;
9207 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9208 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9209 //                              rsurface.batchtvector3f_bufferoffset = 0;
9210                                 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);
9211                         }
9212                         break;
9213                 case Q3DEFORM_BULGE:
9214                         // deform vertex array to make the surface have moving bulges
9215 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9216 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9217 //                      rsurface.batchvertex3f_bufferoffset = 0;
9218 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9219 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9220 //                      rsurface.batchnormal3f_bufferoffset = 0;
9221                         for (j = 0;j < batchnumvertices;j++)
9222                         {
9223                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9224                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9225                         }
9226                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9227                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9228                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9229                         {
9230 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9231 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9232 //                              rsurface.batchsvector3f_bufferoffset = 0;
9233 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchtvector3f_bufferoffset = 0;
9236                                 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);
9237                         }
9238                         break;
9239                 case Q3DEFORM_MOVE:
9240                         // deform vertex array
9241                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9242                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9243                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9244                         VectorScale(deform->parms, scale, waveparms);
9245 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9246 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9247 //                      rsurface.batchvertex3f_bufferoffset = 0;
9248                         for (j = 0;j < batchnumvertices;j++)
9249                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9250                         break;
9251                 }
9252         }
9253
9254         // generate texcoords based on the chosen texcoord source
9255         switch(rsurface.texture->tcgen.tcgen)
9256         {
9257         default:
9258         case Q3TCGEN_TEXTURE:
9259                 break;
9260         case Q3TCGEN_LIGHTMAP:
9261 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9262 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9263 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9264                 if (rsurface.batchtexcoordlightmap2f)
9265                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9266                 break;
9267         case Q3TCGEN_VECTOR:
9268 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9269 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9270 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9271                 for (j = 0;j < batchnumvertices;j++)
9272                 {
9273                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9274                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9275                 }
9276                 break;
9277         case Q3TCGEN_ENVIRONMENT:
9278                 // make environment reflections using a spheremap
9279                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9280                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9281                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9282                 for (j = 0;j < batchnumvertices;j++)
9283                 {
9284                         // identical to Q3A's method, but executed in worldspace so
9285                         // carried models can be shiny too
9286
9287                         float viewer[3], d, reflected[3], worldreflected[3];
9288
9289                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9290                         // VectorNormalize(viewer);
9291
9292                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9293
9294                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9295                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9296                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9297                         // note: this is proportinal to viewer, so we can normalize later
9298
9299                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9300                         VectorNormalize(worldreflected);
9301
9302                         // note: this sphere map only uses world x and z!
9303                         // so positive and negative y will LOOK THE SAME.
9304                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9305                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9306                 }
9307                 break;
9308         }
9309         // the only tcmod that needs software vertex processing is turbulent, so
9310         // check for it here and apply the changes if needed
9311         // and we only support that as the first one
9312         // (handling a mixture of turbulent and other tcmods would be problematic
9313         //  without punting it entirely to a software path)
9314         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9315         {
9316                 amplitude = rsurface.texture->tcmods[0].parms[1];
9317                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9318 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9319 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9320 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9321                 for (j = 0;j < batchnumvertices;j++)
9322                 {
9323                         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);
9324                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9325                 }
9326         }
9327
9328         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9329         {
9330                 // convert the modified arrays to vertex structs
9331 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9332 //              rsurface.batchvertexmeshbuffer = NULL;
9333                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9334                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9335                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9336                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9337                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9339                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9340                 {
9341                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9342                         {
9343                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9344                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9345                         }
9346                 }
9347                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9348                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9349                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9350                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9351                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9352                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9353                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9354                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9355                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9356         }
9357 }
9358
9359 void RSurf_DrawBatch(void)
9360 {
9361         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9362         // through the pipeline, killing it earlier in the pipeline would have
9363         // per-surface overhead rather than per-batch overhead, so it's best to
9364         // reject it here, before it hits glDraw.
9365         if (rsurface.batchnumtriangles == 0)
9366                 return;
9367 #if 0
9368         // batch debugging code
9369         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9370         {
9371                 int i;
9372                 int j;
9373                 int c;
9374                 const int *e;
9375                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9376                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9377                 {
9378                         c = e[i];
9379                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9380                         {
9381                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9382                                 {
9383                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9384                                                 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);
9385                                         break;
9386                                 }
9387                         }
9388                 }
9389         }
9390 #endif
9391         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);
9392 }
9393
9394 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9395 {
9396         // pick the closest matching water plane
9397         int planeindex, vertexindex, bestplaneindex = -1;
9398         float d, bestd;
9399         vec3_t vert;
9400         const float *v;
9401         r_waterstate_waterplane_t *p;
9402         qboolean prepared = false;
9403         bestd = 0;
9404         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9405         {
9406                 if(p->camera_entity != rsurface.texture->camera_entity)
9407                         continue;
9408                 d = 0;
9409                 if(!prepared)
9410                 {
9411                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9412                         prepared = true;
9413                         if(rsurface.batchnumvertices == 0)
9414                                 break;
9415                 }
9416                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9417                 {
9418                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9419                         d += fabs(PlaneDiff(vert, &p->plane));
9420                 }
9421                 if (bestd > d || bestplaneindex < 0)
9422                 {
9423                         bestd = d;
9424                         bestplaneindex = planeindex;
9425                 }
9426         }
9427         return bestplaneindex;
9428         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9429         // this situation though, as it might be better to render single larger
9430         // batches with useless stuff (backface culled for example) than to
9431         // render multiple smaller batches
9432 }
9433
9434 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9435 {
9436         int i;
9437         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9438         rsurface.passcolor4f_vertexbuffer = 0;
9439         rsurface.passcolor4f_bufferoffset = 0;
9440         for (i = 0;i < rsurface.batchnumvertices;i++)
9441                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9442 }
9443
9444 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9445 {
9446         int i;
9447         float f;
9448         const float *v;
9449         const float *c;
9450         float *c2;
9451         if (rsurface.passcolor4f)
9452         {
9453                 // generate color arrays
9454                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9455                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9456                 rsurface.passcolor4f_vertexbuffer = 0;
9457                 rsurface.passcolor4f_bufferoffset = 0;
9458                 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)
9459                 {
9460                         f = RSurf_FogVertex(v);
9461                         c2[0] = c[0] * f;
9462                         c2[1] = c[1] * f;
9463                         c2[2] = c[2] * f;
9464                         c2[3] = c[3];
9465                 }
9466         }
9467         else
9468         {
9469                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9470                 rsurface.passcolor4f_vertexbuffer = 0;
9471                 rsurface.passcolor4f_bufferoffset = 0;
9472                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9473                 {
9474                         f = RSurf_FogVertex(v);
9475                         c2[0] = f;
9476                         c2[1] = f;
9477                         c2[2] = f;
9478                         c2[3] = 1;
9479                 }
9480         }
9481 }
9482
9483 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9484 {
9485         int i;
9486         float f;
9487         const float *v;
9488         const float *c;
9489         float *c2;
9490         if (!rsurface.passcolor4f)
9491                 return;
9492         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494         rsurface.passcolor4f_vertexbuffer = 0;
9495         rsurface.passcolor4f_bufferoffset = 0;
9496         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)
9497         {
9498                 f = RSurf_FogVertex(v);
9499                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9500                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9501                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9502                 c2[3] = c[3];
9503         }
9504 }
9505
9506 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9507 {
9508         int i;
9509         const float *c;
9510         float *c2;
9511         if (!rsurface.passcolor4f)
9512                 return;
9513         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9514         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9515         rsurface.passcolor4f_vertexbuffer = 0;
9516         rsurface.passcolor4f_bufferoffset = 0;
9517         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9518         {
9519                 c2[0] = c[0] * r;
9520                 c2[1] = c[1] * g;
9521                 c2[2] = c[2] * b;
9522                 c2[3] = c[3] * a;
9523         }
9524 }
9525
9526 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9527 {
9528         int i;
9529         const float *c;
9530         float *c2;
9531         if (!rsurface.passcolor4f)
9532                 return;
9533         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9534         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9535         rsurface.passcolor4f_vertexbuffer = 0;
9536         rsurface.passcolor4f_bufferoffset = 0;
9537         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9538         {
9539                 c2[0] = c[0] + r_refdef.scene.ambient;
9540                 c2[1] = c[1] + r_refdef.scene.ambient;
9541                 c2[2] = c[2] + r_refdef.scene.ambient;
9542                 c2[3] = c[3];
9543         }
9544 }
9545
9546 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9547 {
9548         // TODO: optimize
9549         rsurface.passcolor4f = NULL;
9550         rsurface.passcolor4f_vertexbuffer = 0;
9551         rsurface.passcolor4f_bufferoffset = 0;
9552         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9553         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9554         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9555         GL_Color(r, g, b, a);
9556         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9557         RSurf_DrawBatch();
9558 }
9559
9560 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9561 {
9562         // TODO: optimize applyfog && applycolor case
9563         // just apply fog if necessary, and tint the fog color array if necessary
9564         rsurface.passcolor4f = NULL;
9565         rsurface.passcolor4f_vertexbuffer = 0;
9566         rsurface.passcolor4f_bufferoffset = 0;
9567         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9568         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9569         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9570         GL_Color(r, g, b, a);
9571         RSurf_DrawBatch();
9572 }
9573
9574 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9575 {
9576         // TODO: optimize
9577         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9578         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9579         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9580         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9581         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9582         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9583         GL_Color(r, g, b, a);
9584         RSurf_DrawBatch();
9585 }
9586
9587 static void RSurf_DrawBatch_GL11_ClampColor(void)
9588 {
9589         int i;
9590         const float *c1;
9591         float *c2;
9592         if (!rsurface.passcolor4f)
9593                 return;
9594         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9595         {
9596                 c2[0] = bound(0.0f, c1[0], 1.0f);
9597                 c2[1] = bound(0.0f, c1[1], 1.0f);
9598                 c2[2] = bound(0.0f, c1[2], 1.0f);
9599                 c2[3] = bound(0.0f, c1[3], 1.0f);
9600         }
9601 }
9602
9603 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9604 {
9605         int i;
9606         float f;
9607         const float *v;
9608         const float *n;
9609         float *c;
9610         //vec3_t eyedir;
9611
9612         // fake shading
9613         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9614         rsurface.passcolor4f_vertexbuffer = 0;
9615         rsurface.passcolor4f_bufferoffset = 0;
9616         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)
9617         {
9618                 f = -DotProduct(r_refdef.view.forward, n);
9619                 f = max(0, f);
9620                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9621                 f *= r_refdef.lightmapintensity;
9622                 Vector4Set(c, f, f, f, 1);
9623         }
9624 }
9625
9626 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9627 {
9628         RSurf_DrawBatch_GL11_ApplyFakeLight();
9629         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9630         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9631         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9632         GL_Color(r, g, b, a);
9633         RSurf_DrawBatch();
9634 }
9635
9636 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9637 {
9638         int i;
9639         float f;
9640         float alpha;
9641         const float *v;
9642         const float *n;
9643         float *c;
9644         vec3_t ambientcolor;
9645         vec3_t diffusecolor;
9646         vec3_t lightdir;
9647         // TODO: optimize
9648         // model lighting
9649         VectorCopy(rsurface.modellight_lightdir, lightdir);
9650         f = 0.5f * r_refdef.lightmapintensity;
9651         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9652         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9653         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9654         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9655         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9656         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9657         alpha = *a;
9658         if (VectorLength2(diffusecolor) > 0)
9659         {
9660                 // q3-style directional shading
9661                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9662                 rsurface.passcolor4f_vertexbuffer = 0;
9663                 rsurface.passcolor4f_bufferoffset = 0;
9664                 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)
9665                 {
9666                         if ((f = DotProduct(n, lightdir)) > 0)
9667                                 VectorMA(ambientcolor, f, diffusecolor, c);
9668                         else
9669                                 VectorCopy(ambientcolor, c);
9670                         c[3] = alpha;
9671                 }
9672                 *r = 1;
9673                 *g = 1;
9674                 *b = 1;
9675                 *a = 1;
9676                 *applycolor = false;
9677         }
9678         else
9679         {
9680                 *r = ambientcolor[0];
9681                 *g = ambientcolor[1];
9682                 *b = ambientcolor[2];
9683                 rsurface.passcolor4f = NULL;
9684                 rsurface.passcolor4f_vertexbuffer = 0;
9685                 rsurface.passcolor4f_bufferoffset = 0;
9686         }
9687 }
9688
9689 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9690 {
9691         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9692         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9693         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9694         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9695         GL_Color(r, g, b, a);
9696         RSurf_DrawBatch();
9697 }
9698
9699 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9700 {
9701         int i;
9702         float f;
9703         const float *v;
9704         float *c;
9705
9706         // fake shading
9707         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9708         rsurface.passcolor4f_vertexbuffer = 0;
9709         rsurface.passcolor4f_bufferoffset = 0;
9710
9711         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9712         {
9713                 f = 1 - RSurf_FogVertex(v);
9714                 c[0] = r;
9715                 c[1] = g;
9716                 c[2] = b;
9717                 c[3] = f * a;
9718         }
9719 }
9720
9721 void RSurf_SetupDepthAndCulling(void)
9722 {
9723         // submodels are biased to avoid z-fighting with world surfaces that they
9724         // may be exactly overlapping (avoids z-fighting artifacts on certain
9725         // doors and things in Quake maps)
9726         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9727         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9728         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9729         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9730 }
9731
9732 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9733 {
9734         // transparent sky would be ridiculous
9735         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9736                 return;
9737         R_SetupShader_Generic_NoTexture(false, false);
9738         skyrenderlater = true;
9739         RSurf_SetupDepthAndCulling();
9740         GL_DepthMask(true);
9741         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9742         // skymasking on them, and Quake3 never did sky masking (unlike
9743         // software Quake and software Quake2), so disable the sky masking
9744         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9745         // and skymasking also looks very bad when noclipping outside the
9746         // level, so don't use it then either.
9747         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9748         {
9749                 R_Mesh_ResetTextureState();
9750                 if (skyrendermasked)
9751                 {
9752                         R_SetupShader_DepthOrShadow(false, false);
9753                         // depth-only (masking)
9754                         GL_ColorMask(0,0,0,0);
9755                         // just to make sure that braindead drivers don't draw
9756                         // anything despite that colormask...
9757                         GL_BlendFunc(GL_ZERO, GL_ONE);
9758                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9759                         if (rsurface.batchvertex3fbuffer)
9760                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9761                         else
9762                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9763                 }
9764                 else
9765                 {
9766                         R_SetupShader_Generic_NoTexture(false, false);
9767                         // fog sky
9768                         GL_BlendFunc(GL_ONE, GL_ZERO);
9769                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9770                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9771                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9772                 }
9773                 RSurf_DrawBatch();
9774                 if (skyrendermasked)
9775                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9776         }
9777         R_Mesh_ResetTextureState();
9778         GL_Color(1, 1, 1, 1);
9779 }
9780
9781 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9782 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9783 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9784 {
9785         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9786                 return;
9787         if (prepass)
9788         {
9789                 // render screenspace normalmap to texture
9790                 GL_DepthMask(true);
9791                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9792                 RSurf_DrawBatch();
9793                 return;
9794         }
9795
9796         // bind lightmap texture
9797
9798         // water/refraction/reflection/camera surfaces have to be handled specially
9799         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9800         {
9801                 int start, end, startplaneindex;
9802                 for (start = 0;start < texturenumsurfaces;start = end)
9803                 {
9804                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9805                         if(startplaneindex < 0)
9806                         {
9807                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9808                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9809                                 end = start + 1;
9810                                 continue;
9811                         }
9812                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9813                                 ;
9814                         // now that we have a batch using the same planeindex, render it
9815                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9816                         {
9817                                 // render water or distortion background
9818                                 GL_DepthMask(true);
9819                                 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);
9820                                 RSurf_DrawBatch();
9821                                 // blend surface on top
9822                                 GL_DepthMask(false);
9823                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9824                                 RSurf_DrawBatch();
9825                         }
9826                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9827                         {
9828                                 // render surface with reflection texture as input
9829                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9830                                 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);
9831                                 RSurf_DrawBatch();
9832                         }
9833                 }
9834                 return;
9835         }
9836
9837         // render surface batch normally
9838         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9839         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);
9840         RSurf_DrawBatch();
9841 }
9842
9843 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9844 {
9845         // OpenGL 1.3 path - anything not completely ancient
9846         qboolean applycolor;
9847         qboolean applyfog;
9848         int layerindex;
9849         const texturelayer_t *layer;
9850         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);
9851         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9852
9853         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9854         {
9855                 vec4_t layercolor;
9856                 int layertexrgbscale;
9857                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9858                 {
9859                         if (layerindex == 0)
9860                                 GL_AlphaTest(true);
9861                         else
9862                         {
9863                                 GL_AlphaTest(false);
9864                                 GL_DepthFunc(GL_EQUAL);
9865                         }
9866                 }
9867                 GL_DepthMask(layer->depthmask && writedepth);
9868                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9869                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9870                 {
9871                         layertexrgbscale = 4;
9872                         VectorScale(layer->color, 0.25f, layercolor);
9873                 }
9874                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9875                 {
9876                         layertexrgbscale = 2;
9877                         VectorScale(layer->color, 0.5f, layercolor);
9878                 }
9879                 else
9880                 {
9881                         layertexrgbscale = 1;
9882                         VectorScale(layer->color, 1.0f, layercolor);
9883                 }
9884                 layercolor[3] = layer->color[3];
9885                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9886                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9887                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9888                 switch (layer->type)
9889                 {
9890                 case TEXTURELAYERTYPE_LITTEXTURE:
9891                         // single-pass lightmapped texture with 2x rgbscale
9892                         R_Mesh_TexBind(0, r_texture_white);
9893                         R_Mesh_TexMatrix(0, NULL);
9894                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9895                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9896                         R_Mesh_TexBind(1, layer->texture);
9897                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9898                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9899                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9900                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9901                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902                         else if (FAKELIGHT_ENABLED)
9903                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9904                         else if (rsurface.uselightmaptexture)
9905                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9906                         else
9907                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9908                         break;
9909                 case TEXTURELAYERTYPE_TEXTURE:
9910                         // singletexture unlit texture with transparency support
9911                         R_Mesh_TexBind(0, layer->texture);
9912                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9913                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9914                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9915                         R_Mesh_TexBind(1, 0);
9916                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9917                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9918                         break;
9919                 case TEXTURELAYERTYPE_FOG:
9920                         // singletexture fogging
9921                         if (layer->texture)
9922                         {
9923                                 R_Mesh_TexBind(0, layer->texture);
9924                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9925                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9926                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9927                         }
9928                         else
9929                         {
9930                                 R_Mesh_TexBind(0, 0);
9931                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9932                         }
9933                         R_Mesh_TexBind(1, 0);
9934                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9935                         // generate a color array for the fog pass
9936                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9937                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9938                         RSurf_DrawBatch();
9939                         break;
9940                 default:
9941                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9942                 }
9943         }
9944         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9945         {
9946                 GL_DepthFunc(GL_LEQUAL);
9947                 GL_AlphaTest(false);
9948         }
9949 }
9950
9951 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9952 {
9953         // OpenGL 1.1 - crusty old voodoo path
9954         qboolean applyfog;
9955         int layerindex;
9956         const texturelayer_t *layer;
9957         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);
9958         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9959
9960         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9961         {
9962                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9963                 {
9964                         if (layerindex == 0)
9965                                 GL_AlphaTest(true);
9966                         else
9967                         {
9968                                 GL_AlphaTest(false);
9969                                 GL_DepthFunc(GL_EQUAL);
9970                         }
9971                 }
9972                 GL_DepthMask(layer->depthmask && writedepth);
9973                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9974                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9975                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9976                 switch (layer->type)
9977                 {
9978                 case TEXTURELAYERTYPE_LITTEXTURE:
9979                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9980                         {
9981                                 // two-pass lit texture with 2x rgbscale
9982                                 // first the lightmap pass
9983                                 R_Mesh_TexBind(0, r_texture_white);
9984                                 R_Mesh_TexMatrix(0, NULL);
9985                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9986                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9987                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9988                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9989                                 else if (FAKELIGHT_ENABLED)
9990                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9991                                 else if (rsurface.uselightmaptexture)
9992                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9993                                 else
9994                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9995                                 // then apply the texture to it
9996                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9997                                 R_Mesh_TexBind(0, layer->texture);
9998                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9999                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10000                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10001                                 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);
10002                         }
10003                         else
10004                         {
10005                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10006                                 R_Mesh_TexBind(0, layer->texture);
10007                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10008                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10009                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10010                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10011                                         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);
10012                                 else
10013                                         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);
10014                         }
10015                         break;
10016                 case TEXTURELAYERTYPE_TEXTURE:
10017                         // singletexture unlit texture with transparency support
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                         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);
10023                         break;
10024                 case TEXTURELAYERTYPE_FOG:
10025                         // singletexture fogging
10026                         if (layer->texture)
10027                         {
10028                                 R_Mesh_TexBind(0, layer->texture);
10029                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10030                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10031                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10032                         }
10033                         else
10034                         {
10035                                 R_Mesh_TexBind(0, 0);
10036                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10037                         }
10038                         // generate a color array for the fog pass
10039                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10040                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10041                         RSurf_DrawBatch();
10042                         break;
10043                 default:
10044                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10045                 }
10046         }
10047         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10048         {
10049                 GL_DepthFunc(GL_LEQUAL);
10050                 GL_AlphaTest(false);
10051         }
10052 }
10053
10054 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10055 {
10056         int vi;
10057         int j;
10058         r_vertexgeneric_t *batchvertex;
10059         float c[4];
10060
10061 //      R_Mesh_ResetTextureState();
10062         R_SetupShader_Generic_NoTexture(false, false);
10063
10064         if(rsurface.texture && rsurface.texture->currentskinframe)
10065         {
10066                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10067                 c[3] *= rsurface.texture->currentalpha;
10068         }
10069         else
10070         {
10071                 c[0] = 1;
10072                 c[1] = 0;
10073                 c[2] = 1;
10074                 c[3] = 1;
10075         }
10076
10077         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10078         {
10079                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10080                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10081                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10082         }
10083
10084         // brighten it up (as texture value 127 means "unlit")
10085         c[0] *= 2 * r_refdef.view.colorscale;
10086         c[1] *= 2 * r_refdef.view.colorscale;
10087         c[2] *= 2 * r_refdef.view.colorscale;
10088
10089         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10090                 c[3] *= r_wateralpha.value;
10091
10092         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10093         {
10094                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10095                 GL_DepthMask(false);
10096         }
10097         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10098         {
10099                 GL_BlendFunc(GL_ONE, GL_ONE);
10100                 GL_DepthMask(false);
10101         }
10102         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10103         {
10104                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10105                 GL_DepthMask(false);
10106         }
10107         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10108         {
10109                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10110                 GL_DepthMask(false);
10111         }
10112         else
10113         {
10114                 GL_BlendFunc(GL_ONE, GL_ZERO);
10115                 GL_DepthMask(writedepth);
10116         }
10117
10118         if (r_showsurfaces.integer == 3)
10119         {
10120                 rsurface.passcolor4f = NULL;
10121
10122                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10123                 {
10124                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10125
10126                         rsurface.passcolor4f = NULL;
10127                         rsurface.passcolor4f_vertexbuffer = 0;
10128                         rsurface.passcolor4f_bufferoffset = 0;
10129                 }
10130                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10131                 {
10132                         qboolean applycolor = true;
10133                         float one = 1.0;
10134
10135                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10136
10137                         r_refdef.lightmapintensity = 1;
10138                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10139                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10140                 }
10141                 else if (FAKELIGHT_ENABLED)
10142                 {
10143                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10144
10145                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10146                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10147                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10148                 }
10149                 else
10150                 {
10151                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10152
10153                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10154                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10155                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10156                 }
10157
10158                 if(!rsurface.passcolor4f)
10159                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10160
10161                 RSurf_DrawBatch_GL11_ApplyAmbient();
10162                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10163                 if(r_refdef.fogenabled)
10164                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10165                 RSurf_DrawBatch_GL11_ClampColor();
10166
10167                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10168                 R_SetupShader_Generic_NoTexture(false, false);
10169                 RSurf_DrawBatch();
10170         }
10171         else if (!r_refdef.view.showdebug)
10172         {
10173                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10175                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10176                 {
10177                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10178                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10179                 }
10180                 R_Mesh_PrepareVertices_Generic_Unlock();
10181                 RSurf_DrawBatch();
10182         }
10183         else if (r_showsurfaces.integer == 4)
10184         {
10185                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10186                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10187                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10188                 {
10189                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10190                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10191                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10192                 }
10193                 R_Mesh_PrepareVertices_Generic_Unlock();
10194                 RSurf_DrawBatch();
10195         }
10196         else if (r_showsurfaces.integer == 2)
10197         {
10198                 const int *e;
10199                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10201                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10202                 {
10203                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10204                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10205                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10206                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10207                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10208                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10209                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10210                 }
10211                 R_Mesh_PrepareVertices_Generic_Unlock();
10212                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10213         }
10214         else
10215         {
10216                 int texturesurfaceindex;
10217                 int k;
10218                 const msurface_t *surface;
10219                 float surfacecolor4f[4];
10220                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10221                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10222                 vi = 0;
10223                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10224                 {
10225                         surface = texturesurfacelist[texturesurfaceindex];
10226                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10227                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10228                         for (j = 0;j < surface->num_vertices;j++)
10229                         {
10230                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10231                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10232                                 vi++;
10233                         }
10234                 }
10235                 R_Mesh_PrepareVertices_Generic_Unlock();
10236                 RSurf_DrawBatch();
10237         }
10238 }
10239
10240 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10241 {
10242         CHECKGLERROR
10243         RSurf_SetupDepthAndCulling();
10244         if (r_showsurfaces.integer)
10245         {
10246                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10247                 return;
10248         }
10249         switch (vid.renderpath)
10250         {
10251         case RENDERPATH_GL20:
10252         case RENDERPATH_D3D9:
10253         case RENDERPATH_D3D10:
10254         case RENDERPATH_D3D11:
10255         case RENDERPATH_SOFT:
10256         case RENDERPATH_GLES2:
10257                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10258                 break;
10259         case RENDERPATH_GL13:
10260         case RENDERPATH_GLES1:
10261                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10262                 break;
10263         case RENDERPATH_GL11:
10264                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10265                 break;
10266         }
10267         CHECKGLERROR
10268 }
10269
10270 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10271 {
10272         CHECKGLERROR
10273         RSurf_SetupDepthAndCulling();
10274         if (r_showsurfaces.integer)
10275         {
10276                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10277                 return;
10278         }
10279         switch (vid.renderpath)
10280         {
10281         case RENDERPATH_GL20:
10282         case RENDERPATH_D3D9:
10283         case RENDERPATH_D3D10:
10284         case RENDERPATH_D3D11:
10285         case RENDERPATH_SOFT:
10286         case RENDERPATH_GLES2:
10287                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10288                 break;
10289         case RENDERPATH_GL13:
10290         case RENDERPATH_GLES1:
10291                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10292                 break;
10293         case RENDERPATH_GL11:
10294                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10295                 break;
10296         }
10297         CHECKGLERROR
10298 }
10299
10300 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10301 {
10302         int i, j;
10303         int texturenumsurfaces, endsurface;
10304         texture_t *texture;
10305         const msurface_t *surface;
10306         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10307
10308         // if the model is static it doesn't matter what value we give for
10309         // wantnormals and wanttangents, so this logic uses only rules applicable
10310         // to a model, knowing that they are meaningless otherwise
10311         if (ent == r_refdef.scene.worldentity)
10312                 RSurf_ActiveWorldEntity();
10313         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10314                 RSurf_ActiveModelEntity(ent, false, false, false);
10315         else
10316         {
10317                 switch (vid.renderpath)
10318                 {
10319                 case RENDERPATH_GL20:
10320                 case RENDERPATH_D3D9:
10321                 case RENDERPATH_D3D10:
10322                 case RENDERPATH_D3D11:
10323                 case RENDERPATH_SOFT:
10324                 case RENDERPATH_GLES2:
10325                         RSurf_ActiveModelEntity(ent, true, true, false);
10326                         break;
10327                 case RENDERPATH_GL11:
10328                 case RENDERPATH_GL13:
10329                 case RENDERPATH_GLES1:
10330                         RSurf_ActiveModelEntity(ent, true, false, false);
10331                         break;
10332                 }
10333         }
10334
10335         if (r_transparentdepthmasking.integer)
10336         {
10337                 qboolean setup = false;
10338                 for (i = 0;i < numsurfaces;i = j)
10339                 {
10340                         j = i + 1;
10341                         surface = rsurface.modelsurfaces + surfacelist[i];
10342                         texture = surface->texture;
10343                         rsurface.texture = R_GetCurrentTexture(texture);
10344                         rsurface.lightmaptexture = NULL;
10345                         rsurface.deluxemaptexture = NULL;
10346                         rsurface.uselightmaptexture = false;
10347                         // scan ahead until we find a different texture
10348                         endsurface = min(i + 1024, numsurfaces);
10349                         texturenumsurfaces = 0;
10350                         texturesurfacelist[texturenumsurfaces++] = surface;
10351                         for (;j < endsurface;j++)
10352                         {
10353                                 surface = rsurface.modelsurfaces + surfacelist[j];
10354                                 if (texture != surface->texture)
10355                                         break;
10356                                 texturesurfacelist[texturenumsurfaces++] = surface;
10357                         }
10358                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10359                                 continue;
10360                         // render the range of surfaces as depth
10361                         if (!setup)
10362                         {
10363                                 setup = true;
10364                                 GL_ColorMask(0,0,0,0);
10365                                 GL_Color(1,1,1,1);
10366                                 GL_DepthTest(true);
10367                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10368                                 GL_DepthMask(true);
10369 //                              R_Mesh_ResetTextureState();
10370                                 R_SetupShader_DepthOrShadow(false, false);
10371                         }
10372                         RSurf_SetupDepthAndCulling();
10373                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10374                         if (rsurface.batchvertex3fbuffer)
10375                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10376                         else
10377                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10378                         RSurf_DrawBatch();
10379                 }
10380                 if (setup)
10381                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10382         }
10383
10384         for (i = 0;i < numsurfaces;i = j)
10385         {
10386                 j = i + 1;
10387                 surface = rsurface.modelsurfaces + surfacelist[i];
10388                 texture = surface->texture;
10389                 rsurface.texture = R_GetCurrentTexture(texture);
10390                 // scan ahead until we find a different texture
10391                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10392                 texturenumsurfaces = 0;
10393                 texturesurfacelist[texturenumsurfaces++] = surface;
10394                 if(FAKELIGHT_ENABLED)
10395                 {
10396                         rsurface.lightmaptexture = NULL;
10397                         rsurface.deluxemaptexture = NULL;
10398                         rsurface.uselightmaptexture = false;
10399                         for (;j < endsurface;j++)
10400                         {
10401                                 surface = rsurface.modelsurfaces + surfacelist[j];
10402                                 if (texture != surface->texture)
10403                                         break;
10404                                 texturesurfacelist[texturenumsurfaces++] = surface;
10405                         }
10406                 }
10407                 else
10408                 {
10409                         rsurface.lightmaptexture = surface->lightmaptexture;
10410                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10411                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10412                         for (;j < endsurface;j++)
10413                         {
10414                                 surface = rsurface.modelsurfaces + surfacelist[j];
10415                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10416                                         break;
10417                                 texturesurfacelist[texturenumsurfaces++] = surface;
10418                         }
10419                 }
10420                 // render the range of surfaces
10421                 if (ent == r_refdef.scene.worldentity)
10422                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10423                 else
10424                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10425         }
10426         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10427 }
10428
10429 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10430 {
10431         // transparent surfaces get pushed off into the transparent queue
10432         int surfacelistindex;
10433         const msurface_t *surface;
10434         vec3_t tempcenter, center;
10435         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10436         {
10437                 surface = texturesurfacelist[surfacelistindex];
10438                 if (r_transparent_sortsurfacesbynearest.integer)
10439                 {
10440                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10441                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10442                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10443                 }
10444                 else
10445                 {
10446                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10447                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10448                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10449                 }
10450                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10451                 if (rsurface.entity->transparent_offset) // transparent offset
10452                 {
10453                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10454                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10455                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10456                 }
10457                 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);
10458         }
10459 }
10460
10461 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10462 {
10463         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10464                 return;
10465         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10466                 return;
10467         RSurf_SetupDepthAndCulling();
10468         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10469         if (rsurface.batchvertex3fbuffer)
10470                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10471         else
10472                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10473         RSurf_DrawBatch();
10474 }
10475
10476 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10477 {
10478         CHECKGLERROR
10479         if (depthonly)
10480                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10481         else if (prepass)
10482         {
10483                 if (!rsurface.texture->currentnumlayers)
10484                         return;
10485                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10486                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10487                 else
10488                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10489         }
10490         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10491                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10492         else if (!rsurface.texture->currentnumlayers)
10493                 return;
10494         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10495         {
10496                 // in the deferred case, transparent surfaces were queued during prepass
10497                 if (!r_shadow_usingdeferredprepass)
10498                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10499         }
10500         else
10501         {
10502                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10503                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10504         }
10505         CHECKGLERROR
10506 }
10507
10508 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10509 {
10510         int i, j;
10511         texture_t *texture;
10512         R_FrameData_SetMark();
10513         // break the surface list down into batches by texture and use of lightmapping
10514         for (i = 0;i < numsurfaces;i = j)
10515         {
10516                 j = i + 1;
10517                 // texture is the base texture pointer, rsurface.texture is the
10518                 // current frame/skin the texture is directing us to use (for example
10519                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10520                 // use skin 1 instead)
10521                 texture = surfacelist[i]->texture;
10522                 rsurface.texture = R_GetCurrentTexture(texture);
10523                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10524                 {
10525                         // if this texture is not the kind we want, skip ahead to the next one
10526                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10527                                 ;
10528                         continue;
10529                 }
10530                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10531                 {
10532                         rsurface.lightmaptexture = NULL;
10533                         rsurface.deluxemaptexture = NULL;
10534                         rsurface.uselightmaptexture = false;
10535                         // simply scan ahead until we find a different texture or lightmap state
10536                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10537                                 ;
10538                 }
10539                 else
10540                 {
10541                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10542                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10543                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10544                         // simply scan ahead until we find a different texture or lightmap state
10545                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10546                                 ;
10547                 }
10548                 // render the range of surfaces
10549                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10550         }
10551         R_FrameData_ReturnToMark();
10552 }
10553
10554 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10555 {
10556         CHECKGLERROR
10557         if (depthonly)
10558                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10559         else if (prepass)
10560         {
10561                 if (!rsurface.texture->currentnumlayers)
10562                         return;
10563                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10564                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10565                 else
10566                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10567         }
10568         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10569                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10570         else if (!rsurface.texture->currentnumlayers)
10571                 return;
10572         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10573         {
10574                 // in the deferred case, transparent surfaces were queued during prepass
10575                 if (!r_shadow_usingdeferredprepass)
10576                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10577         }
10578         else
10579         {
10580                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10581                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10582         }
10583         CHECKGLERROR
10584 }
10585
10586 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10587 {
10588         int i, j;
10589         texture_t *texture;
10590         R_FrameData_SetMark();
10591         // break the surface list down into batches by texture and use of lightmapping
10592         for (i = 0;i < numsurfaces;i = j)
10593         {
10594                 j = i + 1;
10595                 // texture is the base texture pointer, rsurface.texture is the
10596                 // current frame/skin the texture is directing us to use (for example
10597                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10598                 // use skin 1 instead)
10599                 texture = surfacelist[i]->texture;
10600                 rsurface.texture = R_GetCurrentTexture(texture);
10601                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10602                 {
10603                         // if this texture is not the kind we want, skip ahead to the next one
10604                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10605                                 ;
10606                         continue;
10607                 }
10608                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10609                 {
10610                         rsurface.lightmaptexture = NULL;
10611                         rsurface.deluxemaptexture = NULL;
10612                         rsurface.uselightmaptexture = false;
10613                         // simply scan ahead until we find a different texture or lightmap state
10614                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10615                                 ;
10616                 }
10617                 else
10618                 {
10619                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10620                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10621                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10622                         // simply scan ahead until we find a different texture or lightmap state
10623                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10624                                 ;
10625                 }
10626                 // render the range of surfaces
10627                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10628         }
10629         R_FrameData_ReturnToMark();
10630 }
10631
10632 float locboxvertex3f[6*4*3] =
10633 {
10634         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10635         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10636         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10637         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10638         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10639         1,0,0, 0,0,0, 0,1,0, 1,1,0
10640 };
10641
10642 unsigned short locboxelements[6*2*3] =
10643 {
10644          0, 1, 2, 0, 2, 3,
10645          4, 5, 6, 4, 6, 7,
10646          8, 9,10, 8,10,11,
10647         12,13,14, 12,14,15,
10648         16,17,18, 16,18,19,
10649         20,21,22, 20,22,23
10650 };
10651
10652 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10653 {
10654         int i, j;
10655         cl_locnode_t *loc = (cl_locnode_t *)ent;
10656         vec3_t mins, size;
10657         float vertex3f[6*4*3];
10658         CHECKGLERROR
10659         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10660         GL_DepthMask(false);
10661         GL_DepthRange(0, 1);
10662         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10663         GL_DepthTest(true);
10664         GL_CullFace(GL_NONE);
10665         R_EntityMatrix(&identitymatrix);
10666
10667 //      R_Mesh_ResetTextureState();
10668
10669         i = surfacelist[0];
10670         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10671                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10672                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10673                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10674
10675         if (VectorCompare(loc->mins, loc->maxs))
10676         {
10677                 VectorSet(size, 2, 2, 2);
10678                 VectorMA(loc->mins, -0.5f, size, mins);
10679         }
10680         else
10681         {
10682                 VectorCopy(loc->mins, mins);
10683                 VectorSubtract(loc->maxs, loc->mins, size);
10684         }
10685
10686         for (i = 0;i < 6*4*3;)
10687                 for (j = 0;j < 3;j++, i++)
10688                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10689
10690         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10691         R_SetupShader_Generic_NoTexture(false, false);
10692         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10693 }
10694
10695 void R_DrawLocs(void)
10696 {
10697         int index;
10698         cl_locnode_t *loc, *nearestloc;
10699         vec3_t center;
10700         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10701         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10702         {
10703                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10704                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10705         }
10706 }
10707
10708 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10709 {
10710         if (decalsystem->decals)
10711                 Mem_Free(decalsystem->decals);
10712         memset(decalsystem, 0, sizeof(*decalsystem));
10713 }
10714
10715 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)
10716 {
10717         tridecal_t *decal;
10718         tridecal_t *decals;
10719         int i;
10720
10721         // expand or initialize the system
10722         if (decalsystem->maxdecals <= decalsystem->numdecals)
10723         {
10724                 decalsystem_t old = *decalsystem;
10725                 qboolean useshortelements;
10726                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10727                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10728                 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)));
10729                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10730                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10731                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10732                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10733                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10734                 if (decalsystem->numdecals)
10735                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10736                 if (old.decals)
10737                         Mem_Free(old.decals);
10738                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10739                         decalsystem->element3i[i] = i;
10740                 if (useshortelements)
10741                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10742                                 decalsystem->element3s[i] = i;
10743         }
10744
10745         // grab a decal and search for another free slot for the next one
10746         decals = decalsystem->decals;
10747         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10748         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10749                 ;
10750         decalsystem->freedecal = i;
10751         if (decalsystem->numdecals <= i)
10752                 decalsystem->numdecals = i + 1;
10753
10754         // initialize the decal
10755         decal->lived = 0;
10756         decal->triangleindex = triangleindex;
10757         decal->surfaceindex = surfaceindex;
10758         decal->decalsequence = decalsequence;
10759         decal->color4f[0][0] = c0[0];
10760         decal->color4f[0][1] = c0[1];
10761         decal->color4f[0][2] = c0[2];
10762         decal->color4f[0][3] = 1;
10763         decal->color4f[1][0] = c1[0];
10764         decal->color4f[1][1] = c1[1];
10765         decal->color4f[1][2] = c1[2];
10766         decal->color4f[1][3] = 1;
10767         decal->color4f[2][0] = c2[0];
10768         decal->color4f[2][1] = c2[1];
10769         decal->color4f[2][2] = c2[2];
10770         decal->color4f[2][3] = 1;
10771         decal->vertex3f[0][0] = v0[0];
10772         decal->vertex3f[0][1] = v0[1];
10773         decal->vertex3f[0][2] = v0[2];
10774         decal->vertex3f[1][0] = v1[0];
10775         decal->vertex3f[1][1] = v1[1];
10776         decal->vertex3f[1][2] = v1[2];
10777         decal->vertex3f[2][0] = v2[0];
10778         decal->vertex3f[2][1] = v2[1];
10779         decal->vertex3f[2][2] = v2[2];
10780         decal->texcoord2f[0][0] = t0[0];
10781         decal->texcoord2f[0][1] = t0[1];
10782         decal->texcoord2f[1][0] = t1[0];
10783         decal->texcoord2f[1][1] = t1[1];
10784         decal->texcoord2f[2][0] = t2[0];
10785         decal->texcoord2f[2][1] = t2[1];
10786         TriangleNormal(v0, v1, v2, decal->plane);
10787         VectorNormalize(decal->plane);
10788         decal->plane[3] = DotProduct(v0, decal->plane);
10789 }
10790
10791 extern cvar_t cl_decals_bias;
10792 extern cvar_t cl_decals_models;
10793 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10794 // baseparms, parms, temps
10795 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)
10796 {
10797         int cornerindex;
10798         int index;
10799         float v[9][3];
10800         const float *vertex3f;
10801         const float *normal3f;
10802         int numpoints;
10803         float points[2][9][3];
10804         float temp[3];
10805         float tc[9][2];
10806         float f;
10807         float c[9][4];
10808         const int *e;
10809
10810         e = rsurface.modelelement3i + 3*triangleindex;
10811
10812         vertex3f = rsurface.modelvertex3f;
10813         normal3f = rsurface.modelnormal3f;
10814
10815         if (normal3f)
10816         {
10817                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10818                 {
10819                         index = 3*e[cornerindex];
10820                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10821                 }
10822         }
10823         else
10824         {
10825                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10826                 {
10827                         index = 3*e[cornerindex];
10828                         VectorCopy(vertex3f + index, v[cornerindex]);
10829                 }
10830         }
10831
10832         // cull backfaces
10833         //TriangleNormal(v[0], v[1], v[2], normal);
10834         //if (DotProduct(normal, localnormal) < 0.0f)
10835         //      continue;
10836         // clip by each of the box planes formed from the projection matrix
10837         // if anything survives, we emit the decal
10838         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]);
10839         if (numpoints < 3)
10840                 return;
10841         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]);
10842         if (numpoints < 3)
10843                 return;
10844         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]);
10845         if (numpoints < 3)
10846                 return;
10847         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]);
10848         if (numpoints < 3)
10849                 return;
10850         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]);
10851         if (numpoints < 3)
10852                 return;
10853         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]);
10854         if (numpoints < 3)
10855                 return;
10856         // some part of the triangle survived, so we have to accept it...
10857         if (dynamic)
10858         {
10859                 // dynamic always uses the original triangle
10860                 numpoints = 3;
10861                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10862                 {
10863                         index = 3*e[cornerindex];
10864                         VectorCopy(vertex3f + index, v[cornerindex]);
10865                 }
10866         }
10867         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10868         {
10869                 // convert vertex positions to texcoords
10870                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10871                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10872                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10873                 // calculate distance fade from the projection origin
10874                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10875                 f = bound(0.0f, f, 1.0f);
10876                 c[cornerindex][0] = r * f;
10877                 c[cornerindex][1] = g * f;
10878                 c[cornerindex][2] = b * f;
10879                 c[cornerindex][3] = 1.0f;
10880                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10881         }
10882         if (dynamic)
10883                 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);
10884         else
10885                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10886                         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);
10887 }
10888 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)
10889 {
10890         matrix4x4_t projection;
10891         decalsystem_t *decalsystem;
10892         qboolean dynamic;
10893         dp_model_t *model;
10894         const msurface_t *surface;
10895         const msurface_t *surfaces;
10896         const int *surfacelist;
10897         const texture_t *texture;
10898         int numtriangles;
10899         int numsurfacelist;
10900         int surfacelistindex;
10901         int surfaceindex;
10902         int triangleindex;
10903         float localorigin[3];
10904         float localnormal[3];
10905         float localmins[3];
10906         float localmaxs[3];
10907         float localsize;
10908         //float normal[3];
10909         float planes[6][4];
10910         float angles[3];
10911         bih_t *bih;
10912         int bih_triangles_count;
10913         int bih_triangles[256];
10914         int bih_surfaces[256];
10915
10916         decalsystem = &ent->decalsystem;
10917         model = ent->model;
10918         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10919         {
10920                 R_DecalSystem_Reset(&ent->decalsystem);
10921                 return;
10922         }
10923
10924         if (!model->brush.data_leafs && !cl_decals_models.integer)
10925         {
10926                 if (decalsystem->model)
10927                         R_DecalSystem_Reset(decalsystem);
10928                 return;
10929         }
10930
10931         if (decalsystem->model != model)
10932                 R_DecalSystem_Reset(decalsystem);
10933         decalsystem->model = model;
10934
10935         RSurf_ActiveModelEntity(ent, true, false, false);
10936
10937         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10938         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10939         VectorNormalize(localnormal);
10940         localsize = worldsize*rsurface.inversematrixscale;
10941         localmins[0] = localorigin[0] - localsize;
10942         localmins[1] = localorigin[1] - localsize;
10943         localmins[2] = localorigin[2] - localsize;
10944         localmaxs[0] = localorigin[0] + localsize;
10945         localmaxs[1] = localorigin[1] + localsize;
10946         localmaxs[2] = localorigin[2] + localsize;
10947
10948         //VectorCopy(localnormal, planes[4]);
10949         //VectorVectors(planes[4], planes[2], planes[0]);
10950         AnglesFromVectors(angles, localnormal, NULL, false);
10951         AngleVectors(angles, planes[0], planes[2], planes[4]);
10952         VectorNegate(planes[0], planes[1]);
10953         VectorNegate(planes[2], planes[3]);
10954         VectorNegate(planes[4], planes[5]);
10955         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10956         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10957         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10958         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10959         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10960         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10961
10962 #if 1
10963 // works
10964 {
10965         matrix4x4_t forwardprojection;
10966         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10967         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10968 }
10969 #else
10970 // broken
10971 {
10972         float projectionvector[4][3];
10973         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10974         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10975         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10976         projectionvector[0][0] = planes[0][0] * ilocalsize;
10977         projectionvector[0][1] = planes[1][0] * ilocalsize;
10978         projectionvector[0][2] = planes[2][0] * ilocalsize;
10979         projectionvector[1][0] = planes[0][1] * ilocalsize;
10980         projectionvector[1][1] = planes[1][1] * ilocalsize;
10981         projectionvector[1][2] = planes[2][1] * ilocalsize;
10982         projectionvector[2][0] = planes[0][2] * ilocalsize;
10983         projectionvector[2][1] = planes[1][2] * ilocalsize;
10984         projectionvector[2][2] = planes[2][2] * ilocalsize;
10985         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10986         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10987         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10988         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10989 }
10990 #endif
10991
10992         dynamic = model->surfmesh.isanimated;
10993         numsurfacelist = model->nummodelsurfaces;
10994         surfacelist = model->sortedmodelsurfaces;
10995         surfaces = model->data_surfaces;
10996
10997         bih = NULL;
10998         bih_triangles_count = -1;
10999         if(!dynamic)
11000         {
11001                 if(model->render_bih.numleafs)
11002                         bih = &model->render_bih;
11003                 else if(model->collision_bih.numleafs)
11004                         bih = &model->collision_bih;
11005         }
11006         if(bih)
11007                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11008         if(bih_triangles_count == 0)
11009                 return;
11010         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11011                 return;
11012         if(bih_triangles_count > 0)
11013         {
11014                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11015                 {
11016                         surfaceindex = bih_surfaces[triangleindex];
11017                         surface = surfaces + surfaceindex;
11018                         texture = surface->texture;
11019                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11020                                 continue;
11021                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11022                                 continue;
11023                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11024                 }
11025         }
11026         else
11027         {
11028                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11029                 {
11030                         surfaceindex = surfacelist[surfacelistindex];
11031                         surface = surfaces + surfaceindex;
11032                         // check cull box first because it rejects more than any other check
11033                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11034                                 continue;
11035                         // skip transparent surfaces
11036                         texture = surface->texture;
11037                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11038                                 continue;
11039                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11040                                 continue;
11041                         numtriangles = surface->num_triangles;
11042                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11043                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11044                 }
11045         }
11046 }
11047
11048 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11049 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)
11050 {
11051         int renderentityindex;
11052         float worldmins[3];
11053         float worldmaxs[3];
11054         entity_render_t *ent;
11055
11056         if (!cl_decals_newsystem.integer)
11057                 return;
11058
11059         worldmins[0] = worldorigin[0] - worldsize;
11060         worldmins[1] = worldorigin[1] - worldsize;
11061         worldmins[2] = worldorigin[2] - worldsize;
11062         worldmaxs[0] = worldorigin[0] + worldsize;
11063         worldmaxs[1] = worldorigin[1] + worldsize;
11064         worldmaxs[2] = worldorigin[2] + worldsize;
11065
11066         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11067
11068         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11069         {
11070                 ent = r_refdef.scene.entities[renderentityindex];
11071                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11072                         continue;
11073
11074                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11075         }
11076 }
11077
11078 typedef struct r_decalsystem_splatqueue_s
11079 {
11080         vec3_t worldorigin;
11081         vec3_t worldnormal;
11082         float color[4];
11083         float tcrange[4];
11084         float worldsize;
11085         int decalsequence;
11086 }
11087 r_decalsystem_splatqueue_t;
11088
11089 int r_decalsystem_numqueued = 0;
11090 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11091
11092 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)
11093 {
11094         r_decalsystem_splatqueue_t *queue;
11095
11096         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11097                 return;
11098
11099         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11100         VectorCopy(worldorigin, queue->worldorigin);
11101         VectorCopy(worldnormal, queue->worldnormal);
11102         Vector4Set(queue->color, r, g, b, a);
11103         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11104         queue->worldsize = worldsize;
11105         queue->decalsequence = cl.decalsequence++;
11106 }
11107
11108 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11109 {
11110         int i;
11111         r_decalsystem_splatqueue_t *queue;
11112
11113         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11114                 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);
11115         r_decalsystem_numqueued = 0;
11116 }
11117
11118 extern cvar_t cl_decals_max;
11119 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11120 {
11121         int i;
11122         decalsystem_t *decalsystem = &ent->decalsystem;
11123         int numdecals;
11124         int killsequence;
11125         tridecal_t *decal;
11126         float frametime;
11127         float lifetime;
11128
11129         if (!decalsystem->numdecals)
11130                 return;
11131
11132         if (r_showsurfaces.integer)
11133                 return;
11134
11135         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11136         {
11137                 R_DecalSystem_Reset(decalsystem);
11138                 return;
11139         }
11140
11141         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11142         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11143
11144         if (decalsystem->lastupdatetime)
11145                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11146         else
11147                 frametime = 0;
11148         decalsystem->lastupdatetime = r_refdef.scene.time;
11149         decal = decalsystem->decals;
11150         numdecals = decalsystem->numdecals;
11151
11152         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11153         {
11154                 if (decal->color4f[0][3])
11155                 {
11156                         decal->lived += frametime;
11157                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11158                         {
11159                                 memset(decal, 0, sizeof(*decal));
11160                                 if (decalsystem->freedecal > i)
11161                                         decalsystem->freedecal = i;
11162                         }
11163                 }
11164         }
11165         decal = decalsystem->decals;
11166         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11167                 numdecals--;
11168
11169         // collapse the array by shuffling the tail decals into the gaps
11170         for (;;)
11171         {
11172                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11173                         decalsystem->freedecal++;
11174                 if (decalsystem->freedecal == numdecals)
11175                         break;
11176                 decal[decalsystem->freedecal] = decal[--numdecals];
11177         }
11178
11179         decalsystem->numdecals = numdecals;
11180
11181         if (numdecals <= 0)
11182         {
11183                 // if there are no decals left, reset decalsystem
11184                 R_DecalSystem_Reset(decalsystem);
11185         }
11186 }
11187
11188 extern skinframe_t *decalskinframe;
11189 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11190 {
11191         int i;
11192         decalsystem_t *decalsystem = &ent->decalsystem;
11193         int numdecals;
11194         tridecal_t *decal;
11195         float faderate;
11196         float alpha;
11197         float *v3f;
11198         float *c4f;
11199         float *t2f;
11200         const int *e;
11201         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11202         int numtris = 0;
11203
11204         numdecals = decalsystem->numdecals;
11205         if (!numdecals)
11206                 return;
11207
11208         if (r_showsurfaces.integer)
11209                 return;
11210
11211         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11212         {
11213                 R_DecalSystem_Reset(decalsystem);
11214                 return;
11215         }
11216
11217         // if the model is static it doesn't matter what value we give for
11218         // wantnormals and wanttangents, so this logic uses only rules applicable
11219         // to a model, knowing that they are meaningless otherwise
11220         if (ent == r_refdef.scene.worldentity)
11221                 RSurf_ActiveWorldEntity();
11222         else
11223                 RSurf_ActiveModelEntity(ent, false, false, false);
11224
11225         decalsystem->lastupdatetime = r_refdef.scene.time;
11226         decal = decalsystem->decals;
11227
11228         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11229
11230         // update vertex positions for animated models
11231         v3f = decalsystem->vertex3f;
11232         c4f = decalsystem->color4f;
11233         t2f = decalsystem->texcoord2f;
11234         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11235         {
11236                 if (!decal->color4f[0][3])
11237                         continue;
11238
11239                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11240                         continue;
11241
11242                 // skip backfaces
11243                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11244                         continue;
11245
11246                 // update color values for fading decals
11247                 if (decal->lived >= cl_decals_time.value)
11248                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11249                 else
11250                         alpha = 1.0f;
11251
11252                 c4f[ 0] = decal->color4f[0][0] * alpha;
11253                 c4f[ 1] = decal->color4f[0][1] * alpha;
11254                 c4f[ 2] = decal->color4f[0][2] * alpha;
11255                 c4f[ 3] = 1;
11256                 c4f[ 4] = decal->color4f[1][0] * alpha;
11257                 c4f[ 5] = decal->color4f[1][1] * alpha;
11258                 c4f[ 6] = decal->color4f[1][2] * alpha;
11259                 c4f[ 7] = 1;
11260                 c4f[ 8] = decal->color4f[2][0] * alpha;
11261                 c4f[ 9] = decal->color4f[2][1] * alpha;
11262                 c4f[10] = decal->color4f[2][2] * alpha;
11263                 c4f[11] = 1;
11264
11265                 t2f[0] = decal->texcoord2f[0][0];
11266                 t2f[1] = decal->texcoord2f[0][1];
11267                 t2f[2] = decal->texcoord2f[1][0];
11268                 t2f[3] = decal->texcoord2f[1][1];
11269                 t2f[4] = decal->texcoord2f[2][0];
11270                 t2f[5] = decal->texcoord2f[2][1];
11271
11272                 // update vertex positions for animated models
11273                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11274                 {
11275                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11276                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11277                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11278                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11279                 }
11280                 else
11281                 {
11282                         VectorCopy(decal->vertex3f[0], v3f);
11283                         VectorCopy(decal->vertex3f[1], v3f + 3);
11284                         VectorCopy(decal->vertex3f[2], v3f + 6);
11285                 }
11286
11287                 if (r_refdef.fogenabled)
11288                 {
11289                         alpha = RSurf_FogVertex(v3f);
11290                         VectorScale(c4f, alpha, c4f);
11291                         alpha = RSurf_FogVertex(v3f + 3);
11292                         VectorScale(c4f + 4, alpha, c4f + 4);
11293                         alpha = RSurf_FogVertex(v3f + 6);
11294                         VectorScale(c4f + 8, alpha, c4f + 8);
11295                 }
11296
11297                 v3f += 9;
11298                 c4f += 12;
11299                 t2f += 6;
11300                 numtris++;
11301         }
11302
11303         if (numtris > 0)
11304         {
11305                 r_refdef.stats.drawndecals += numtris;
11306
11307                 // now render the decals all at once
11308                 // (this assumes they all use one particle font texture!)
11309                 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);
11310 //              R_Mesh_ResetTextureState();
11311                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11312                 GL_DepthMask(false);
11313                 GL_DepthRange(0, 1);
11314                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11315                 GL_DepthTest(true);
11316                 GL_CullFace(GL_NONE);
11317                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11318                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11319                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11320         }
11321 }
11322
11323 static void R_DrawModelDecals(void)
11324 {
11325         int i, numdecals;
11326
11327         // fade faster when there are too many decals
11328         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11329         for (i = 0;i < r_refdef.scene.numentities;i++)
11330                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11331
11332         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11333         for (i = 0;i < r_refdef.scene.numentities;i++)
11334                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11335                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11336
11337         R_DecalSystem_ApplySplatEntitiesQueue();
11338
11339         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11340         for (i = 0;i < r_refdef.scene.numentities;i++)
11341                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11342
11343         r_refdef.stats.totaldecals += numdecals;
11344
11345         if (r_showsurfaces.integer)
11346                 return;
11347
11348         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11349
11350         for (i = 0;i < r_refdef.scene.numentities;i++)
11351         {
11352                 if (!r_refdef.viewcache.entityvisible[i])
11353                         continue;
11354                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11355                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11356         }
11357 }
11358
11359 extern cvar_t mod_collision_bih;
11360 static void R_DrawDebugModel(void)
11361 {
11362         entity_render_t *ent = rsurface.entity;
11363         int i, j, k, l, flagsmask;
11364         const msurface_t *surface;
11365         dp_model_t *model = ent->model;
11366         vec3_t v;
11367
11368         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11369                 return;
11370
11371         if (r_showoverdraw.value > 0)
11372         {
11373                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11374                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11375                 R_SetupShader_Generic_NoTexture(false, false);
11376                 GL_DepthTest(false);
11377                 GL_DepthMask(false);
11378                 GL_DepthRange(0, 1);
11379                 GL_BlendFunc(GL_ONE, GL_ONE);
11380                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11381                 {
11382                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11383                                 continue;
11384                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11385                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11386                         {
11387                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11388                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11389                                 if (!rsurface.texture->currentlayers->depthmask)
11390                                         GL_Color(c, 0, 0, 1.0f);
11391                                 else if (ent == r_refdef.scene.worldentity)
11392                                         GL_Color(c, c, c, 1.0f);
11393                                 else
11394                                         GL_Color(0, c, 0, 1.0f);
11395                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11396                                 RSurf_DrawBatch();
11397                         }
11398                 }
11399                 rsurface.texture = NULL;
11400         }
11401
11402         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11403
11404 //      R_Mesh_ResetTextureState();
11405         R_SetupShader_Generic_NoTexture(false, false);
11406         GL_DepthRange(0, 1);
11407         GL_DepthTest(!r_showdisabledepthtest.integer);
11408         GL_DepthMask(false);
11409         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11410
11411         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11412         {
11413                 int triangleindex;
11414                 int bihleafindex;
11415                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11416                 const q3mbrush_t *brush;
11417                 const bih_t *bih = &model->collision_bih;
11418                 const bih_leaf_t *bihleaf;
11419                 float vertex3f[3][3];
11420                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11421                 cullbox = false;
11422                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11423                 {
11424                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11425                                 continue;
11426                         switch (bihleaf->type)
11427                         {
11428                         case BIH_BRUSH:
11429                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11430                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11431                                 {
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(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11434                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11435                                 }
11436                                 break;
11437                         case BIH_COLLISIONTRIANGLE:
11438                                 triangleindex = bihleaf->itemindex;
11439                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11440                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11441                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11442                                 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);
11443                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11444                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11445                                 break;
11446                         case BIH_RENDERTRIANGLE:
11447                                 triangleindex = bihleaf->itemindex;
11448                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11449                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11450                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11451                                 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);
11452                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11453                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11454                                 break;
11455                         }
11456                 }
11457         }
11458
11459         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11460
11461 #ifndef USE_GLES2
11462         if (r_showtris.integer && qglPolygonMode)
11463         {
11464                 if (r_showdisabledepthtest.integer)
11465                 {
11466                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11467                         GL_DepthMask(false);
11468                 }
11469                 else
11470                 {
11471                         GL_BlendFunc(GL_ONE, GL_ZERO);
11472                         GL_DepthMask(true);
11473                 }
11474                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11475                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11476                 {
11477                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11478                                 continue;
11479                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11480                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11481                         {
11482                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11483                                 if (!rsurface.texture->currentlayers->depthmask)
11484                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11485                                 else if (ent == r_refdef.scene.worldentity)
11486                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11487                                 else
11488                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11489                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11490                                 RSurf_DrawBatch();
11491                         }
11492                 }
11493                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11494                 rsurface.texture = NULL;
11495         }
11496
11497         if (r_shownormals.value != 0 && qglBegin)
11498         {
11499                 if (r_showdisabledepthtest.integer)
11500                 {
11501                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11502                         GL_DepthMask(false);
11503                 }
11504                 else
11505                 {
11506                         GL_BlendFunc(GL_ONE, GL_ZERO);
11507                         GL_DepthMask(true);
11508                 }
11509                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11510                 {
11511                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11512                                 continue;
11513                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11514                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11515                         {
11516                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11517                                 qglBegin(GL_LINES);
11518                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11519                                 {
11520                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11521                                         {
11522                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11523                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11524                                                 qglVertex3f(v[0], v[1], v[2]);
11525                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11526                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11527                                                 qglVertex3f(v[0], v[1], v[2]);
11528                                         }
11529                                 }
11530                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11531                                 {
11532                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11533                                         {
11534                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11535                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11536                                                 qglVertex3f(v[0], v[1], v[2]);
11537                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11538                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11539                                                 qglVertex3f(v[0], v[1], v[2]);
11540                                         }
11541                                 }
11542                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11543                                 {
11544                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11545                                         {
11546                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11547                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11548                                                 qglVertex3f(v[0], v[1], v[2]);
11549                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11550                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11551                                                 qglVertex3f(v[0], v[1], v[2]);
11552                                         }
11553                                 }
11554                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11555                                 {
11556                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11557                                         {
11558                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11559                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11560                                                 qglVertex3f(v[0], v[1], v[2]);
11561                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11562                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11563                                                 qglVertex3f(v[0], v[1], v[2]);
11564                                         }
11565                                 }
11566                                 qglEnd();
11567                                 CHECKGLERROR
11568                         }
11569                 }
11570                 rsurface.texture = NULL;
11571         }
11572 #endif
11573 }
11574
11575 int r_maxsurfacelist = 0;
11576 const msurface_t **r_surfacelist = NULL;
11577 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11578 {
11579         int i, j, endj, flagsmask;
11580         dp_model_t *model = r_refdef.scene.worldmodel;
11581         msurface_t *surfaces;
11582         unsigned char *update;
11583         int numsurfacelist = 0;
11584         if (model == NULL)
11585                 return;
11586
11587         if (r_maxsurfacelist < model->num_surfaces)
11588         {
11589                 r_maxsurfacelist = model->num_surfaces;
11590                 if (r_surfacelist)
11591                         Mem_Free((msurface_t**)r_surfacelist);
11592                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11593         }
11594
11595         RSurf_ActiveWorldEntity();
11596
11597         surfaces = model->data_surfaces;
11598         update = model->brushq1.lightmapupdateflags;
11599
11600         // update light styles on this submodel
11601         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11602         {
11603                 model_brush_lightstyleinfo_t *style;
11604                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11605                 {
11606                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11607                         {
11608                                 int *list = style->surfacelist;
11609                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11610                                 for (j = 0;j < style->numsurfaces;j++)
11611                                         update[list[j]] = true;
11612                         }
11613                 }
11614         }
11615
11616         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11617
11618         if (debug)
11619         {
11620                 R_DrawDebugModel();
11621                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11622                 return;
11623         }
11624
11625         rsurface.lightmaptexture = NULL;
11626         rsurface.deluxemaptexture = NULL;
11627         rsurface.uselightmaptexture = false;
11628         rsurface.texture = NULL;
11629         rsurface.rtlight = NULL;
11630         numsurfacelist = 0;
11631         // add visible surfaces to draw list
11632         for (i = 0;i < model->nummodelsurfaces;i++)
11633         {
11634                 j = model->sortedmodelsurfaces[i];
11635                 if (r_refdef.viewcache.world_surfacevisible[j])
11636                         r_surfacelist[numsurfacelist++] = surfaces + j;
11637         }
11638         // update lightmaps if needed
11639         if (model->brushq1.firstrender)
11640         {
11641                 model->brushq1.firstrender = false;
11642                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11643                         if (update[j])
11644                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11645         }
11646         else if (update)
11647         {
11648                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11649                         if (r_refdef.viewcache.world_surfacevisible[j])
11650                                 if (update[j])
11651                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11652         }
11653         // don't do anything if there were no surfaces
11654         if (!numsurfacelist)
11655         {
11656                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11657                 return;
11658         }
11659         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11660
11661         // add to stats if desired
11662         if (r_speeds.integer && !skysurfaces && !depthonly)
11663         {
11664                 r_refdef.stats.world_surfaces += numsurfacelist;
11665                 for (j = 0;j < numsurfacelist;j++)
11666                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11667         }
11668
11669         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11670 }
11671
11672 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11673 {
11674         int i, j, endj, flagsmask;
11675         dp_model_t *model = ent->model;
11676         msurface_t *surfaces;
11677         unsigned char *update;
11678         int numsurfacelist = 0;
11679         if (model == NULL)
11680                 return;
11681
11682         if (r_maxsurfacelist < model->num_surfaces)
11683         {
11684                 r_maxsurfacelist = model->num_surfaces;
11685                 if (r_surfacelist)
11686                         Mem_Free((msurface_t **)r_surfacelist);
11687                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11688         }
11689
11690         // if the model is static it doesn't matter what value we give for
11691         // wantnormals and wanttangents, so this logic uses only rules applicable
11692         // to a model, knowing that they are meaningless otherwise
11693         if (ent == r_refdef.scene.worldentity)
11694                 RSurf_ActiveWorldEntity();
11695         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11696                 RSurf_ActiveModelEntity(ent, false, false, false);
11697         else if (prepass)
11698                 RSurf_ActiveModelEntity(ent, true, true, true);
11699         else if (depthonly)
11700         {
11701                 switch (vid.renderpath)
11702                 {
11703                 case RENDERPATH_GL20:
11704                 case RENDERPATH_D3D9:
11705                 case RENDERPATH_D3D10:
11706                 case RENDERPATH_D3D11:
11707                 case RENDERPATH_SOFT:
11708                 case RENDERPATH_GLES2:
11709                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11710                         break;
11711                 case RENDERPATH_GL11:
11712                 case RENDERPATH_GL13:
11713                 case RENDERPATH_GLES1:
11714                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11715                         break;
11716                 }
11717         }
11718         else
11719         {
11720                 switch (vid.renderpath)
11721                 {
11722                 case RENDERPATH_GL20:
11723                 case RENDERPATH_D3D9:
11724                 case RENDERPATH_D3D10:
11725                 case RENDERPATH_D3D11:
11726                 case RENDERPATH_SOFT:
11727                 case RENDERPATH_GLES2:
11728                         RSurf_ActiveModelEntity(ent, true, true, false);
11729                         break;
11730                 case RENDERPATH_GL11:
11731                 case RENDERPATH_GL13:
11732                 case RENDERPATH_GLES1:
11733                         RSurf_ActiveModelEntity(ent, true, false, false);
11734                         break;
11735                 }
11736         }
11737
11738         surfaces = model->data_surfaces;
11739         update = model->brushq1.lightmapupdateflags;
11740
11741         // update light styles
11742         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11743         {
11744                 model_brush_lightstyleinfo_t *style;
11745                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11746                 {
11747                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11748                         {
11749                                 int *list = style->surfacelist;
11750                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11751                                 for (j = 0;j < style->numsurfaces;j++)
11752                                         update[list[j]] = true;
11753                         }
11754                 }
11755         }
11756
11757         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11758
11759         if (debug)
11760         {
11761                 R_DrawDebugModel();
11762                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11763                 return;
11764         }
11765
11766         rsurface.lightmaptexture = NULL;
11767         rsurface.deluxemaptexture = NULL;
11768         rsurface.uselightmaptexture = false;
11769         rsurface.texture = NULL;
11770         rsurface.rtlight = NULL;
11771         numsurfacelist = 0;
11772         // add visible surfaces to draw list
11773         for (i = 0;i < model->nummodelsurfaces;i++)
11774                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11775         // don't do anything if there were no surfaces
11776         if (!numsurfacelist)
11777         {
11778                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11779                 return;
11780         }
11781         // update lightmaps if needed
11782         if (update)
11783         {
11784                 int updated = 0;
11785                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11786                 {
11787                         if (update[j])
11788                         {
11789                                 updated++;
11790                                 R_BuildLightMap(ent, surfaces + j);
11791                         }
11792                 }
11793         }
11794         if (update)
11795                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11796                         if (update[j])
11797                                 R_BuildLightMap(ent, surfaces + j);
11798         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11799
11800         // add to stats if desired
11801         if (r_speeds.integer && !skysurfaces && !depthonly)
11802         {
11803                 r_refdef.stats.entities_surfaces += numsurfacelist;
11804                 for (j = 0;j < numsurfacelist;j++)
11805                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11806         }
11807
11808         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11809 }
11810
11811 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11812 {
11813         static texture_t texture;
11814         static msurface_t surface;
11815         const msurface_t *surfacelist = &surface;
11816
11817         // fake enough texture and surface state to render this geometry
11818
11819         texture.update_lastrenderframe = -1; // regenerate this texture
11820         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11821         texture.currentskinframe = skinframe;
11822         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11823         texture.offsetmapping = OFFSETMAPPING_OFF;
11824         texture.offsetscale = 1;
11825         texture.specularscalemod = 1;
11826         texture.specularpowermod = 1;
11827
11828         surface.texture = &texture;
11829         surface.num_triangles = numtriangles;
11830         surface.num_firsttriangle = firsttriangle;
11831         surface.num_vertices = numvertices;
11832         surface.num_firstvertex = firstvertex;
11833
11834         // now render it
11835         rsurface.texture = R_GetCurrentTexture(surface.texture);
11836         rsurface.lightmaptexture = NULL;
11837         rsurface.deluxemaptexture = NULL;
11838         rsurface.uselightmaptexture = false;
11839         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11840 }
11841
11842 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)
11843 {
11844         static msurface_t surface;
11845         const msurface_t *surfacelist = &surface;
11846
11847         // fake enough texture and surface state to render this geometry
11848         surface.texture = texture;
11849         surface.num_triangles = numtriangles;
11850         surface.num_firsttriangle = firsttriangle;
11851         surface.num_vertices = numvertices;
11852         surface.num_firstvertex = firstvertex;
11853
11854         // now render it
11855         rsurface.texture = R_GetCurrentTexture(surface.texture);
11856         rsurface.lightmaptexture = NULL;
11857         rsurface.deluxemaptexture = NULL;
11858         rsurface.uselightmaptexture = false;
11859         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11860 }