]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix Collision_ClipTrace_Line_Sphere calculation of impactdist (had a
[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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 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)"};
144 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"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 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"};
151 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"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 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"};
155 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)"};
156 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)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 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)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 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)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 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)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 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"};
167 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."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177
178 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)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 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"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 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"};
185 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"};
186 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)"};
187
188 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
189 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
190 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
191 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
192
193 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
194 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
195
196 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
197 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
198 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
199 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
200 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
201
202 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
203 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 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"};
214
215 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"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 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"};
223
224 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."};
225
226 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)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 static qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -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_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
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+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+3+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)
1967 {
1968         unsigned int permutation = 0;
1969         if (r_trippy.integer && !notrippy)
1970                 permutation |= SHADERPERMUTATION_TRIPPY;
1971         if (vid.allowalphatocoverage)
1972                 GL_AlphaToCoverage(false);
1973         switch (vid.renderpath)
1974         {
1975         case RENDERPATH_D3D9:
1976 #ifdef SUPPORTD3D
1977                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1978 #endif
1979                 break;
1980         case RENDERPATH_D3D10:
1981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982                 break;
1983         case RENDERPATH_D3D11:
1984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1985                 break;
1986         case RENDERPATH_GL20:
1987         case RENDERPATH_GLES2:
1988                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1989                 break;
1990         case RENDERPATH_GL13:
1991         case RENDERPATH_GLES1:
1992                 R_Mesh_TexBind(0, 0);
1993                 R_Mesh_TexBind(1, 0);
1994                 break;
1995         case RENDERPATH_GL11:
1996                 R_Mesh_TexBind(0, 0);
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2000                 break;
2001         }
2002 }
2003
2004 void R_SetupShader_ShowDepth(qboolean notrippy)
2005 {
2006         int permutation = 0;
2007         if (r_trippy.integer && !notrippy)
2008                 permutation |= SHADERPERMUTATION_TRIPPY;
2009         if (vid.allowalphatocoverage)
2010                 GL_AlphaToCoverage(false);
2011         switch (vid.renderpath)
2012         {
2013         case RENDERPATH_D3D9:
2014 #ifdef SUPPORTHLSL
2015                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2016 #endif
2017                 break;
2018         case RENDERPATH_D3D10:
2019                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2020                 break;
2021         case RENDERPATH_D3D11:
2022                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2023                 break;
2024         case RENDERPATH_GL20:
2025         case RENDERPATH_GLES2:
2026                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         case RENDERPATH_GL13:
2029         case RENDERPATH_GLES1:
2030                 break;
2031         case RENDERPATH_GL11:
2032                 break;
2033         case RENDERPATH_SOFT:
2034                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2035                 break;
2036         }
2037 }
2038
2039 extern qboolean r_shadow_usingdeferredprepass;
2040 extern cvar_t r_shadow_deferred_8bitrange;
2041 extern rtexture_t *r_shadow_attenuationgradienttexture;
2042 extern rtexture_t *r_shadow_attenuation2dtexture;
2043 extern rtexture_t *r_shadow_attenuation3dtexture;
2044 extern qboolean r_shadow_usingshadowmap2d;
2045 extern qboolean r_shadow_usingshadowmaportho;
2046 extern float r_shadow_shadowmap_texturescale[2];
2047 extern float r_shadow_shadowmap_parameters[4];
2048 extern qboolean r_shadow_shadowmapvsdct;
2049 extern qboolean r_shadow_shadowmapsampler;
2050 extern int r_shadow_shadowmappcf;
2051 extern rtexture_t *r_shadow_shadowmap2dtexture;
2052 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2053 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2054 extern matrix4x4_t r_shadow_shadowmapmatrix;
2055 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2056 extern int r_shadow_prepass_width;
2057 extern int r_shadow_prepass_height;
2058 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2059 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2060 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
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                 }
2225                 if (rsurface.texture->reflectmasktexture)
2226                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2228                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2229                 if (vid.allowalphatocoverage)
2230                         GL_AlphaToCoverage(false);
2231         }
2232         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2233         {
2234                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2235                 {
2236                         switch(rsurface.texture->offsetmapping)
2237                         {
2238                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2239                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_OFF: break;
2242                         }
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246                 // unshaded geometry (fullbright or ambient model lighting)
2247                 mode = SHADERMODE_FLATCOLOR;
2248                 ambientscale = diffusescale = specularscale = 0;
2249                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250                         permutation |= SHADERPERMUTATION_GLOW;
2251                 if (r_refdef.fogenabled)
2252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253                 if (rsurface.texture->colormapping)
2254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2255                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256                 {
2257                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259
2260                         if (r_shadow_shadowmapsampler)
2261                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262                         if (r_shadow_shadowmappcf > 1)
2263                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264                         else if (r_shadow_shadowmappcf)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266                 }
2267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268                         permutation |= SHADERPERMUTATION_REFLECTION;
2269                 if (rsurface.texture->reflectmasktexture)
2270                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2271                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273                 // when using alphatocoverage, we don't need alphakill
2274                 if (vid.allowalphatocoverage)
2275                 {
2276                         if (r_transparent_alphatocoverage.integer)
2277                         {
2278                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2279                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2280                         }
2281                         else
2282                                 GL_AlphaToCoverage(false);
2283                 }
2284         }
2285         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2286         {
2287                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2288                 {
2289                         switch(rsurface.texture->offsetmapping)
2290                         {
2291                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2292                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_OFF: break;
2295                         }
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299                 // directional model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmapsampler)
2316                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317                         if (r_shadow_shadowmappcf > 1)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319                         else if (r_shadow_shadowmappcf)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 // when using alphatocoverage, we don't need alphakill
2337                 if (vid.allowalphatocoverage)
2338                 {
2339                         if (r_transparent_alphatocoverage.integer)
2340                         {
2341                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2342                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2343                         }
2344                         else
2345                                 GL_AlphaToCoverage(false);
2346                 }
2347         }
2348         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2349         {
2350                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2351                 {
2352                         switch(rsurface.texture->offsetmapping)
2353                         {
2354                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2355                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_OFF: break;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // ambient model lighting
2363                 mode = SHADERMODE_LIGHTDIRECTION;
2364                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2365                         permutation |= SHADERPERMUTATION_GLOW;
2366                 if (r_refdef.fogenabled)
2367                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2368                 if (rsurface.texture->colormapping)
2369                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2370                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371                 {
2372                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2373                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374
2375                         if (r_shadow_shadowmapsampler)
2376                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2377                         if (r_shadow_shadowmappcf > 1)
2378                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2379                         else if (r_shadow_shadowmappcf)
2380                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2383                         permutation |= SHADERPERMUTATION_REFLECTION;
2384                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2385                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2386                 if (rsurface.texture->reflectmasktexture)
2387                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2388                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2389                 {
2390                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2391                         if (r_shadow_bouncegriddirectional)
2392                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2393                 }
2394                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2395                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 // when using alphatocoverage, we don't need alphakill
2397                 if (vid.allowalphatocoverage)
2398                 {
2399                         if (r_transparent_alphatocoverage.integer)
2400                         {
2401                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2402                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2403                         }
2404                         else
2405                                 GL_AlphaToCoverage(false);
2406                 }
2407         }
2408         else
2409         {
2410                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2411                 {
2412                         switch(rsurface.texture->offsetmapping)
2413                         {
2414                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2415                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2416                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2417                         case OFFSETMAPPING_OFF: break;
2418                         }
2419                 }
2420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2421                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2422                 // lightmapped wall
2423                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2424                         permutation |= SHADERPERMUTATION_GLOW;
2425                 if (r_refdef.fogenabled)
2426                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2427                 if (rsurface.texture->colormapping)
2428                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2429                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2430                 {
2431                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2432                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2433
2434                         if (r_shadow_shadowmapsampler)
2435                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2436                         if (r_shadow_shadowmappcf > 1)
2437                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2438                         else if (r_shadow_shadowmappcf)
2439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2442                         permutation |= SHADERPERMUTATION_REFLECTION;
2443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2445                 if (rsurface.texture->reflectmasktexture)
2446                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2447                 if (FAKELIGHT_ENABLED)
2448                 {
2449                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2450                         mode = SHADERMODE_FAKELIGHT;
2451                         permutation |= SHADERPERMUTATION_DIFFUSE;
2452                         if (specularscale > 0)
2453                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2454                 }
2455                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2456                 {
2457                         // deluxemapping (light direction texture)
2458                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2459                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2460                         else
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (r_glsl_deluxemapping.integer >= 2)
2467                 {
2468                         // fake deluxemapping (uniform light direction in tangentspace)
2469                         if (rsurface.uselightmaptexture)
2470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2471                         else
2472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2473                         permutation |= SHADERPERMUTATION_DIFFUSE;
2474                         if (specularscale > 0)
2475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476                 }
2477                 else if (rsurface.uselightmaptexture)
2478                 {
2479                         // ordinary lightmapping (q1bsp, q3bsp)
2480                         mode = SHADERMODE_LIGHTMAP;
2481                 }
2482                 else
2483                 {
2484                         // ordinary vertex coloring (q3bsp)
2485                         mode = SHADERMODE_VERTEXCOLOR;
2486                 }
2487                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2488                 {
2489                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2490                         if (r_shadow_bouncegriddirectional)
2491                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492                 }
2493                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2495                 // when using alphatocoverage, we don't need alphakill
2496                 if (vid.allowalphatocoverage)
2497                 {
2498                         if (r_transparent_alphatocoverage.integer)
2499                         {
2500                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2501                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2502                         }
2503                         else
2504                                 GL_AlphaToCoverage(false);
2505                 }
2506         }
2507         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2508                 colormod = dummy_colormod;
2509         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2510                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2511         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2512                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2513         switch(vid.renderpath)
2514         {
2515         case RENDERPATH_D3D9:
2516 #ifdef SUPPORTD3D
2517                 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);
2518                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2519                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2520                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2521                 if (mode == SHADERMODE_LIGHTSOURCE)
2522                 {
2523                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2524                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2525                 }
2526                 else
2527                 {
2528                         if (mode == SHADERMODE_LIGHTDIRECTION)
2529                         {
2530                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2531                         }
2532                 }
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2535                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2536                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2537                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2546
2547                         // additive passes are only darkened by fog, not tinted
2548                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2549                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2550                 }
2551                 else
2552                 {
2553                         if (mode == SHADERMODE_FLATCOLOR)
2554                         {
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2556                         }
2557                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2558                         {
2559                                 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]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2566                         }
2567                         else
2568                         {
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[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] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2574                         }
2575                         // additive passes are only darkened by fog, not tinted
2576                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2578                         else
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2580                         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);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2588                         if (mode == SHADERMODE_WATER)
2589                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2590                 }
2591                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2592                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2593                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2594                 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));
2595                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2596                 if (rsurface.texture->pantstexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2600                 if (rsurface.texture->shirttexture)
2601                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2602                 else
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2608                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2609                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2610                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2612                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2613                         );
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2617                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2618
2619                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2620                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2621                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2622                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2628                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2630                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2631                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2632                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2633                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2634                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2635                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2636                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2637                 {
2638                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2639                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2640                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642                 else
2643                 {
2644                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2647 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2649                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2650                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2651                 {
2652                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2653                         if (rsurface.rtlight)
2654                         {
2655                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2656                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2657                         }
2658                 }
2659 #endif
2660                 break;
2661         case RENDERPATH_D3D10:
2662                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2663                 break;
2664         case RENDERPATH_D3D11:
2665                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2666                 break;
2667         case RENDERPATH_GL20:
2668         case RENDERPATH_GLES2:
2669                 if (!vid.useinterleavedarrays)
2670                 {
2671                         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);
2672                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2673                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2679                 }
2680                 else
2681                 {
2682                         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);
2683                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2684                 }
2685                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2687                 if (mode == SHADERMODE_LIGHTSOURCE)
2688                 {
2689                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2690                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2691                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2692                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2693                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2694                         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);
2695         
2696                         // additive passes are only darkened by fog, not tinted
2697                         if (r_glsl_permutation->loc_FogColor >= 0)
2698                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2699                         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);
2700                 }
2701                 else
2702                 {
2703                         if (mode == SHADERMODE_FLATCOLOR)
2704                         {
2705                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2706                         }
2707                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2708                         {
2709                                 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]);
2710                                 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]);
2711                                 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);
2712                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2713                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2714                                 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]);
2715                                 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]);
2716                         }
2717                         else
2718                         {
2719                                 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]);
2720                                 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]);
2721                                 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);
2722                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2723                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2724                         }
2725                         // additive passes are only darkened by fog, not tinted
2726                         if (r_glsl_permutation->loc_FogColor >= 0)
2727                         {
2728                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2729                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2730                                 else
2731                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2732                         }
2733                         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);
2734                         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]);
2735                         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]);
2736                         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]);
2737                         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]);
2738                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2739                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2740                         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);
2741                         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]);
2742                 }
2743                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2744                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2745                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2746                 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]);
2747                 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]);
2748
2749                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2750                 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));
2751                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2752                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2753                 {
2754                         if (rsurface.texture->pantstexture)
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2756                         else
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2758                 }
2759                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2760                 {
2761                         if (rsurface.texture->shirttexture)
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2763                         else
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2765                 }
2766                 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]);
2767                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2768                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2769                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2770                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2771                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2772                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2773                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2774                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2775                         );
2776                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2777                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2778                 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]);
2779                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2780                 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);}
2781                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2782
2783                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2784                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2785                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2786                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2787                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2788                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2789                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2794                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2795                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2796                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2797                 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);
2798                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2799                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2800                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2801                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2802                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2803                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2804                 {
2805                         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);
2806                         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);
2807                         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);
2808                 }
2809                 else
2810                 {
2811                         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);
2812                 }
2813                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2814                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2815                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2816                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2817                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2818                 {
2819                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2820                         if (rsurface.rtlight)
2821                         {
2822                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2823                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2824                         }
2825                 }
2826                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2827                 CHECKGLERROR
2828                 break;
2829         case RENDERPATH_GL11:
2830         case RENDERPATH_GL13:
2831         case RENDERPATH_GLES1:
2832                 break;
2833         case RENDERPATH_SOFT:
2834                 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);
2835                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2836                 R_SetupShader_SetPermutationSoft(mode, permutation);
2837                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2838                 if (mode == SHADERMODE_LIGHTSOURCE)
2839                 {
2840                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2846         
2847                         // additive passes are only darkened by fog, not tinted
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2849                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2850                 }
2851                 else
2852                 {
2853                         if (mode == SHADERMODE_FLATCOLOR)
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2856                         }
2857                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2858                         {
2859                                 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]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2861                                 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);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2864                                 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]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2866                         }
2867                         else
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2871                                 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);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2874                         }
2875                         // additive passes are only darkened by fog, not tinted
2876                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2878                         else
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2880                         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);
2881                         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]);
2882                         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]);
2883                         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]);
2884                         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]);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2888                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2889                 }
2890                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2891                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2892                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2893                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2894                 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]);
2895
2896                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2897                 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));
2898                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2899                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2900                 {
2901                         if (rsurface.texture->pantstexture)
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2903                         else
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2905                 }
2906                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2907                 {
2908                         if (rsurface.texture->shirttexture)
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2910                         else
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2912                 }
2913                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2917                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2918                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2919                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2920                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2921                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2922                         );
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2927
2928                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2929                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2930                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2931                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2940                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2941                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2942                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2943                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2944                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2945                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2946                 {
2947                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2948                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2949                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2950                 }
2951                 else
2952                 {
2953                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954                 }
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2991         // light source
2992         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2993         if (rtlight->currentcubemap != r_texture_whitecube)
2994                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2995         if (diffusescale > 0)
2996                 permutation |= SHADERPERMUTATION_DIFFUSE;
2997         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2998                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2999         if (r_shadow_usingshadowmap2d)
3000         {
3001                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3002                 if (r_shadow_shadowmapvsdct)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3004
3005                 if (r_shadow_shadowmapsampler)
3006                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3007                 if (r_shadow_shadowmappcf > 1)
3008                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3009                 else if (r_shadow_shadowmappcf)
3010                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3011         }
3012         if (vid.allowalphatocoverage)
3013                 GL_AlphaToCoverage(false);
3014         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3015         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3016         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3017         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3018         switch(vid.renderpath)
3019         {
3020         case RENDERPATH_D3D9:
3021 #ifdef SUPPORTD3D
3022                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3024                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3028                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3029                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3030                 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);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3033
3034                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3035                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3036                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3037                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3038                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3039                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3040 #endif
3041                 break;
3042         case RENDERPATH_D3D10:
3043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3044                 break;
3045         case RENDERPATH_D3D11:
3046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3047                 break;
3048         case RENDERPATH_GL20:
3049         case RENDERPATH_GLES2:
3050                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3051                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3052                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3053                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3054                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3055                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3056                 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]);
3057                 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]);
3058                 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);
3059                 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]);
3060                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3061
3062                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3063                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3064                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3065                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3066                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3067                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3068                 break;
3069         case RENDERPATH_GL11:
3070         case RENDERPATH_GL13:
3071         case RENDERPATH_GLES1:
3072                 break;
3073         case RENDERPATH_SOFT:
3074                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3076                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3081                 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]);
3082                 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);
3083                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3084                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3085
3086                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3087                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3088                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3089                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3090                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3091                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3092                 break;
3093         }
3094 }
3095
3096 #define SKINFRAME_HASH 1024
3097
3098 typedef struct
3099 {
3100         int loadsequence; // incremented each level change
3101         memexpandablearray_t array;
3102         skinframe_t *hash[SKINFRAME_HASH];
3103 }
3104 r_skinframe_t;
3105 r_skinframe_t r_skinframe;
3106
3107 void R_SkinFrame_PrepareForPurge(void)
3108 {
3109         r_skinframe.loadsequence++;
3110         // wrap it without hitting zero
3111         if (r_skinframe.loadsequence >= 200)
3112                 r_skinframe.loadsequence = 1;
3113 }
3114
3115 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3116 {
3117         if (!skinframe)
3118                 return;
3119         // mark the skinframe as used for the purging code
3120         skinframe->loadsequence = r_skinframe.loadsequence;
3121 }
3122
3123 void R_SkinFrame_Purge(void)
3124 {
3125         int i;
3126         skinframe_t *s;
3127         for (i = 0;i < SKINFRAME_HASH;i++)
3128         {
3129                 for (s = r_skinframe.hash[i];s;s = s->next)
3130                 {
3131                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3132                         {
3133                                 if (s->merged == s->base)
3134                                         s->merged = NULL;
3135                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3136                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3137                                 R_PurgeTexture(s->merged);s->merged = NULL;
3138                                 R_PurgeTexture(s->base  );s->base   = NULL;
3139                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3140                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3141                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3142                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3143                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3144                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3145                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3146                                 s->loadsequence = 0;
3147                         }
3148                 }
3149         }
3150 }
3151
3152 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3153         skinframe_t *item;
3154         char basename[MAX_QPATH];
3155
3156         Image_StripImageExtension(name, basename, sizeof(basename));
3157
3158         if( last == NULL ) {
3159                 int hashindex;
3160                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3161                 item = r_skinframe.hash[hashindex];
3162         } else {
3163                 item = last->next;
3164         }
3165
3166         // linearly search through the hash bucket
3167         for( ; item ; item = item->next ) {
3168                 if( !strcmp( item->basename, basename ) ) {
3169                         return item;
3170                 }
3171         }
3172         return NULL;
3173 }
3174
3175 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3176 {
3177         skinframe_t *item;
3178         int hashindex;
3179         char basename[MAX_QPATH];
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3185                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3186                         break;
3187
3188         if (!item) {
3189                 rtexture_t *dyntexture;
3190                 // check whether its a dynamic texture
3191                 dyntexture = CL_GetDynTexture( basename );
3192                 if (!add && !dyntexture)
3193                         return NULL;
3194                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3195                 memset(item, 0, sizeof(*item));
3196                 strlcpy(item->basename, basename, sizeof(item->basename));
3197                 item->base = dyntexture; // either NULL or dyntexture handle
3198                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3199                 item->comparewidth = comparewidth;
3200                 item->compareheight = compareheight;
3201                 item->comparecrc = comparecrc;
3202                 item->next = r_skinframe.hash[hashindex];
3203                 r_skinframe.hash[hashindex] = item;
3204         }
3205         else if (textureflags & TEXF_FORCE_RELOAD)
3206         {
3207                 rtexture_t *dyntexture;
3208                 // check whether its a dynamic texture
3209                 dyntexture = CL_GetDynTexture( basename );
3210                 if (!add && !dyntexture)
3211                         return NULL;
3212                 if (item->merged == item->base)
3213                         item->merged = NULL;
3214                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3215                 R_PurgeTexture(item->stain );item->stain  = NULL;
3216                 R_PurgeTexture(item->merged);item->merged = NULL;
3217                 R_PurgeTexture(item->base  );item->base   = NULL;
3218                 R_PurgeTexture(item->pants );item->pants  = NULL;
3219                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3220                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3221                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3222                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3223                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3224         R_PurgeTexture(item->reflect);item->reflect = NULL;
3225                 item->loadsequence = 0;
3226         }
3227         else if( item->base == NULL )
3228         {
3229                 rtexture_t *dyntexture;
3230                 // check whether its a dynamic texture
3231                 // 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]
3232                 dyntexture = CL_GetDynTexture( basename );
3233                 item->base = dyntexture; // either NULL or dyntexture handle
3234         }
3235
3236         R_SkinFrame_MarkUsed(item);
3237         return item;
3238 }
3239
3240 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3241         { \
3242                 unsigned long long avgcolor[5], wsum; \
3243                 int pix, comp, w; \
3244                 avgcolor[0] = 0; \
3245                 avgcolor[1] = 0; \
3246                 avgcolor[2] = 0; \
3247                 avgcolor[3] = 0; \
3248                 avgcolor[4] = 0; \
3249                 wsum = 0; \
3250                 for(pix = 0; pix < cnt; ++pix) \
3251                 { \
3252                         w = 0; \
3253                         for(comp = 0; comp < 3; ++comp) \
3254                                 w += getpixel; \
3255                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3256                         { \
3257                                 ++wsum; \
3258                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3259                                 w = getpixel; \
3260                                 for(comp = 0; comp < 3; ++comp) \
3261                                         avgcolor[comp] += getpixel * w; \
3262                                 avgcolor[3] += w; \
3263                         } \
3264                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3265                         avgcolor[4] += getpixel; \
3266                 } \
3267                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3268                         avgcolor[3] = 1; \
3269                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3272                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3273         }
3274
3275 extern cvar_t gl_picmip;
3276 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3277 {
3278         int j;
3279         unsigned char *pixels;
3280         unsigned char *bumppixels;
3281         unsigned char *basepixels = NULL;
3282         int basepixels_width = 0;
3283         int basepixels_height = 0;
3284         skinframe_t *skinframe;
3285         rtexture_t *ddsbase = NULL;
3286         qboolean ddshasalpha = false;
3287         float ddsavgcolor[4];
3288         char basename[MAX_QPATH];
3289         int miplevel = R_PicmipForFlags(textureflags);
3290         int savemiplevel = miplevel;
3291         int mymiplevel;
3292         char vabuf[1024];
3293
3294         if (cls.state == ca_dedicated)
3295                 return NULL;
3296
3297         // return an existing skinframe if already loaded
3298         // if loading of the first image fails, don't make a new skinframe as it
3299         // would cause all future lookups of this to be missing
3300         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3301         if (skinframe && skinframe->base)
3302                 return skinframe;
3303
3304         Image_StripImageExtension(name, basename, sizeof(basename));
3305
3306         // check for DDS texture file first
3307         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3308         {
3309                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3310                 if (basepixels == NULL)
3311                         return NULL;
3312         }
3313
3314         // FIXME handle miplevel
3315
3316         if (developer_loading.integer)
3317                 Con_Printf("loading skin \"%s\"\n", name);
3318
3319         // we've got some pixels to store, so really allocate this new texture now
3320         if (!skinframe)
3321                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3322         textureflags &= ~TEXF_FORCE_RELOAD;
3323         skinframe->stain = NULL;
3324         skinframe->merged = NULL;
3325         skinframe->base = NULL;
3326         skinframe->pants = NULL;
3327         skinframe->shirt = NULL;
3328         skinframe->nmap = NULL;
3329         skinframe->gloss = NULL;
3330         skinframe->glow = NULL;
3331         skinframe->fog = NULL;
3332         skinframe->reflect = NULL;
3333         skinframe->hasalpha = false;
3334
3335         if (ddsbase)
3336         {
3337                 skinframe->base = ddsbase;
3338                 skinframe->hasalpha = ddshasalpha;
3339                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3340                 if (r_loadfog && skinframe->hasalpha)
3341                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3342                 //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]);
3343         }
3344         else
3345         {
3346                 basepixels_width = image_width;
3347                 basepixels_height = image_height;
3348                 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);
3349                 if (textureflags & TEXF_ALPHA)
3350                 {
3351                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3352                         {
3353                                 if (basepixels[j] < 255)
3354                                 {
3355                                         skinframe->hasalpha = true;
3356                                         break;
3357                                 }
3358                         }
3359                         if (r_loadfog && skinframe->hasalpha)
3360                         {
3361                                 // has transparent pixels
3362                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3363                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3364                                 {
3365                                         pixels[j+0] = 255;
3366                                         pixels[j+1] = 255;
3367                                         pixels[j+2] = 255;
3368                                         pixels[j+3] = basepixels[j+3];
3369                                 }
3370                                 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);
3371                                 Mem_Free(pixels);
3372                         }
3373                 }
3374                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3375 #ifndef USE_GLES2
3376                 //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]);
3377                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3378                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3379                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3380                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3381 #endif
3382         }
3383
3384         if (r_loaddds)
3385         {
3386                 mymiplevel = savemiplevel;
3387                 if (r_loadnormalmap)
3388                         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);
3389                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3390                 if (r_loadgloss)
3391                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3392                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3393                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3394                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3395         }
3396
3397         // _norm is the name used by tenebrae and has been adopted as standard
3398         if (r_loadnormalmap && skinframe->nmap == NULL)
3399         {
3400                 mymiplevel = savemiplevel;
3401                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3402                 {
3403                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3404                         Mem_Free(pixels);
3405                         pixels = NULL;
3406                 }
3407                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3408                 {
3409                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3410                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3411                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3412                         Mem_Free(pixels);
3413                         Mem_Free(bumppixels);
3414                 }
3415                 else if (r_shadow_bumpscale_basetexture.value > 0)
3416                 {
3417                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3418                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3419                         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);
3420                         Mem_Free(pixels);
3421                 }
3422 #ifndef USE_GLES2
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3424                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3425 #endif
3426         }
3427
3428         // _luma is supported only for tenebrae compatibility
3429         // _glow is the preferred name
3430         mymiplevel = savemiplevel;
3431         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))))
3432         {
3433                 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);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3436                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438                 Mem_Free(pixels);pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 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);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3447                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3459                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         mymiplevel = savemiplevel;
3466         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3467         {
3468                 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);
3469 #ifndef USE_GLES2
3470                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3471                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3472 #endif
3473                 Mem_Free(pixels);
3474                 pixels = NULL;
3475         }
3476
3477         mymiplevel = savemiplevel;
3478         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3479         {
3480                 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);
3481 #ifndef USE_GLES2
3482                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3483                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3484 #endif
3485                 Mem_Free(pixels);
3486                 pixels = NULL;
3487         }
3488
3489         if (basepixels)
3490                 Mem_Free(basepixels);
3491
3492         return skinframe;
3493 }
3494
3495 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3496 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3497 {
3498         int i;
3499         unsigned char *temp1, *temp2;
3500         skinframe_t *skinframe;
3501         char vabuf[1024];
3502
3503         if (cls.state == ca_dedicated)
3504                 return NULL;
3505
3506         // if already loaded just return it, otherwise make a new skinframe
3507         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3508         if (skinframe && skinframe->base)
3509                 return skinframe;
3510         textureflags &= ~TEXF_FORCE_RELOAD;
3511
3512         skinframe->stain = NULL;
3513         skinframe->merged = NULL;
3514         skinframe->base = NULL;
3515         skinframe->pants = NULL;
3516         skinframe->shirt = NULL;
3517         skinframe->nmap = NULL;
3518         skinframe->gloss = NULL;
3519         skinframe->glow = NULL;
3520         skinframe->fog = NULL;
3521         skinframe->reflect = NULL;
3522         skinframe->hasalpha = false;
3523
3524         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3525         if (!skindata)
3526                 return NULL;
3527
3528         if (developer_loading.integer)
3529                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3530
3531         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3532         {
3533                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3534                 temp2 = temp1 + width * height * 4;
3535                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3536                 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);
3537                 Mem_Free(temp1);
3538         }
3539         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3540         if (textureflags & TEXF_ALPHA)
3541         {
3542                 for (i = 3;i < width * height * 4;i += 4)
3543                 {
3544                         if (skindata[i] < 255)
3545                         {
3546                                 skinframe->hasalpha = true;
3547                                 break;
3548                         }
3549                 }
3550                 if (r_loadfog && skinframe->hasalpha)
3551                 {
3552                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3553                         memcpy(fogpixels, skindata, width * height * 4);
3554                         for (i = 0;i < width * height * 4;i += 4)
3555                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3556                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3557                         Mem_Free(fogpixels);
3558                 }
3559         }
3560
3561         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3562         //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]);
3563
3564         return skinframe;
3565 }
3566
3567 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3568 {
3569         int i;
3570         int featuresmask;
3571         skinframe_t *skinframe;
3572
3573         if (cls.state == ca_dedicated)
3574                 return NULL;
3575
3576         // if already loaded just return it, otherwise make a new skinframe
3577         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3578         if (skinframe && skinframe->base)
3579                 return skinframe;
3580         textureflags &= ~TEXF_FORCE_RELOAD;
3581
3582         skinframe->stain = NULL;
3583         skinframe->merged = NULL;
3584         skinframe->base = NULL;
3585         skinframe->pants = NULL;
3586         skinframe->shirt = NULL;
3587         skinframe->nmap = NULL;
3588         skinframe->gloss = NULL;
3589         skinframe->glow = NULL;
3590         skinframe->fog = NULL;
3591         skinframe->reflect = NULL;
3592         skinframe->hasalpha = false;
3593
3594         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3595         if (!skindata)
3596                 return NULL;
3597
3598         if (developer_loading.integer)
3599                 Con_Printf("loading quake skin \"%s\"\n", name);
3600
3601         // 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)
3602         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3603         memcpy(skinframe->qpixels, skindata, width*height);
3604         skinframe->qwidth = width;
3605         skinframe->qheight = height;
3606
3607         featuresmask = 0;
3608         for (i = 0;i < width * height;i++)
3609                 featuresmask |= palette_featureflags[skindata[i]];
3610
3611         skinframe->hasalpha = false;
3612         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3613         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3614         skinframe->qgeneratemerged = true;
3615         skinframe->qgeneratebase = skinframe->qhascolormapping;
3616         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3617
3618         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3619         //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]);
3620
3621         return skinframe;
3622 }
3623
3624 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3625 {
3626         int width;
3627         int height;
3628         unsigned char *skindata;
3629         char vabuf[1024];
3630
3631         if (!skinframe->qpixels)
3632                 return;
3633
3634         if (!skinframe->qhascolormapping)
3635                 colormapped = false;
3636
3637         if (colormapped)
3638         {
3639                 if (!skinframe->qgeneratebase)
3640                         return;
3641         }
3642         else
3643         {
3644                 if (!skinframe->qgeneratemerged)
3645                         return;
3646         }
3647
3648         width = skinframe->qwidth;
3649         height = skinframe->qheight;
3650         skindata = skinframe->qpixels;
3651
3652         if (skinframe->qgeneratenmap)
3653         {
3654                 unsigned char *temp1, *temp2;
3655                 skinframe->qgeneratenmap = false;
3656                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3657                 temp2 = temp1 + width * height * 4;
3658                 // use either a custom palette or the quake palette
3659                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3660                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3661                 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);
3662                 Mem_Free(temp1);
3663         }
3664
3665         if (skinframe->qgenerateglow)
3666         {
3667                 skinframe->qgenerateglow = false;
3668                 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
3669         }
3670
3671         if (colormapped)
3672         {
3673                 skinframe->qgeneratebase = false;
3674                 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);
3675                 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);
3676                 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);
3677         }
3678         else
3679         {
3680                 skinframe->qgeneratemerged = false;
3681                 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);
3682         }
3683
3684         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3685         {
3686                 Mem_Free(skinframe->qpixels);
3687                 skinframe->qpixels = NULL;
3688         }
3689 }
3690
3691 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)
3692 {
3693         int i;
3694         skinframe_t *skinframe;
3695         char vabuf[1024];
3696
3697         if (cls.state == ca_dedicated)
3698                 return NULL;
3699
3700         // if already loaded just return it, otherwise make a new skinframe
3701         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3702         if (skinframe && skinframe->base)
3703                 return skinframe;
3704         textureflags &= ~TEXF_FORCE_RELOAD;
3705
3706         skinframe->stain = NULL;
3707         skinframe->merged = NULL;
3708         skinframe->base = NULL;
3709         skinframe->pants = NULL;
3710         skinframe->shirt = NULL;
3711         skinframe->nmap = NULL;
3712         skinframe->gloss = NULL;
3713         skinframe->glow = NULL;
3714         skinframe->fog = NULL;
3715         skinframe->reflect = NULL;
3716         skinframe->hasalpha = false;
3717
3718         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3719         if (!skindata)
3720                 return NULL;
3721
3722         if (developer_loading.integer)
3723                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3724
3725         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3726         if (textureflags & TEXF_ALPHA)
3727         {
3728                 for (i = 0;i < width * height;i++)
3729                 {
3730                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3731                         {
3732                                 skinframe->hasalpha = true;
3733                                 break;
3734                         }
3735                 }
3736                 if (r_loadfog && skinframe->hasalpha)
3737                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3738         }
3739
3740         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3741         //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]);
3742
3743         return skinframe;
3744 }
3745
3746 skinframe_t *R_SkinFrame_LoadMissing(void)
3747 {
3748         skinframe_t *skinframe;
3749
3750         if (cls.state == ca_dedicated)
3751                 return NULL;
3752
3753         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3754         skinframe->stain = NULL;
3755         skinframe->merged = NULL;
3756         skinframe->base = NULL;
3757         skinframe->pants = NULL;
3758         skinframe->shirt = NULL;
3759         skinframe->nmap = NULL;
3760         skinframe->gloss = NULL;
3761         skinframe->glow = NULL;
3762         skinframe->fog = NULL;
3763         skinframe->reflect = NULL;
3764         skinframe->hasalpha = false;
3765
3766         skinframe->avgcolor[0] = rand() / RAND_MAX;
3767         skinframe->avgcolor[1] = rand() / RAND_MAX;
3768         skinframe->avgcolor[2] = rand() / RAND_MAX;
3769         skinframe->avgcolor[3] = 1;
3770
3771         return skinframe;
3772 }
3773
3774 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3775 typedef struct suffixinfo_s
3776 {
3777         const char *suffix;
3778         qboolean flipx, flipy, flipdiagonal;
3779 }
3780 suffixinfo_t;
3781 static suffixinfo_t suffix[3][6] =
3782 {
3783         {
3784                 {"px",   false, false, false},
3785                 {"nx",   false, false, false},
3786                 {"py",   false, false, false},
3787                 {"ny",   false, false, false},
3788                 {"pz",   false, false, false},
3789                 {"nz",   false, false, false}
3790         },
3791         {
3792                 {"posx", false, false, false},
3793                 {"negx", false, false, false},
3794                 {"posy", false, false, false},
3795                 {"negy", false, false, false},
3796                 {"posz", false, false, false},
3797                 {"negz", false, false, false}
3798         },
3799         {
3800                 {"rt",    true, false,  true},
3801                 {"lf",   false,  true,  true},
3802                 {"ft",    true,  true, false},
3803                 {"bk",   false, false, false},
3804                 {"up",    true, false,  true},
3805                 {"dn",    true, false,  true}
3806         }
3807 };
3808
3809 static int componentorder[4] = {0, 1, 2, 3};
3810
3811 static rtexture_t *R_LoadCubemap(const char *basename)
3812 {
3813         int i, j, cubemapsize;
3814         unsigned char *cubemappixels, *image_buffer;
3815         rtexture_t *cubemaptexture;
3816         char name[256];
3817         // must start 0 so the first loadimagepixels has no requested width/height
3818         cubemapsize = 0;
3819         cubemappixels = NULL;
3820         cubemaptexture = NULL;
3821         // keep trying different suffix groups (posx, px, rt) until one loads
3822         for (j = 0;j < 3 && !cubemappixels;j++)
3823         {
3824                 // load the 6 images in the suffix group
3825                 for (i = 0;i < 6;i++)
3826                 {
3827                         // generate an image name based on the base and and suffix
3828                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3829                         // load it
3830                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3831                         {
3832                                 // an image loaded, make sure width and height are equal
3833                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3834                                 {
3835                                         // if this is the first image to load successfully, allocate the cubemap memory
3836                                         if (!cubemappixels && image_width >= 1)
3837                                         {
3838                                                 cubemapsize = image_width;
3839                                                 // note this clears to black, so unavailable sides are black
3840                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3841                                         }
3842                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3843                                         if (cubemappixels)
3844                                                 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);
3845                                 }
3846                                 else
3847                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3848                                 // free the image
3849                                 Mem_Free(image_buffer);
3850                         }
3851                 }
3852         }
3853         // if a cubemap loaded, upload it
3854         if (cubemappixels)
3855         {
3856                 if (developer_loading.integer)
3857                         Con_Printf("loading cubemap \"%s\"\n", basename);
3858
3859                 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);
3860                 Mem_Free(cubemappixels);
3861         }
3862         else
3863         {
3864                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3865                 if (developer_loading.integer)
3866                 {
3867                         Con_Printf("(tried tried images ");
3868                         for (j = 0;j < 3;j++)
3869                                 for (i = 0;i < 6;i++)
3870                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3871                         Con_Print(" and was unable to find any of them).\n");
3872                 }
3873         }
3874         return cubemaptexture;
3875 }
3876
3877 rtexture_t *R_GetCubemap(const char *basename)
3878 {
3879         int i;
3880         for (i = 0;i < r_texture_numcubemaps;i++)
3881                 if (r_texture_cubemaps[i] != NULL)
3882                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3883                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3884         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3885                 return r_texture_whitecube;
3886         r_texture_numcubemaps++;
3887         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3888         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3889         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3890         return r_texture_cubemaps[i]->texture;
3891 }
3892
3893 static void R_Main_FreeViewCache(void)
3894 {
3895         if (r_refdef.viewcache.entityvisible)
3896                 Mem_Free(r_refdef.viewcache.entityvisible);
3897         if (r_refdef.viewcache.world_pvsbits)
3898                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3899         if (r_refdef.viewcache.world_leafvisible)
3900                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3901         if (r_refdef.viewcache.world_surfacevisible)
3902                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3903         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3904 }
3905
3906 static void R_Main_ResizeViewCache(void)
3907 {
3908         int numentities = r_refdef.scene.numentities;
3909         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3910         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3911         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3912         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3913         if (r_refdef.viewcache.maxentities < numentities)
3914         {
3915                 r_refdef.viewcache.maxentities = numentities;
3916                 if (r_refdef.viewcache.entityvisible)
3917                         Mem_Free(r_refdef.viewcache.entityvisible);
3918                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3919         }
3920         if (r_refdef.viewcache.world_numclusters != numclusters)
3921         {
3922                 r_refdef.viewcache.world_numclusters = numclusters;
3923                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3924                 if (r_refdef.viewcache.world_pvsbits)
3925                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3926                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3927         }
3928         if (r_refdef.viewcache.world_numleafs != numleafs)
3929         {
3930                 r_refdef.viewcache.world_numleafs = numleafs;
3931                 if (r_refdef.viewcache.world_leafvisible)
3932                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3933                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3934         }
3935         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3936         {
3937                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3938                 if (r_refdef.viewcache.world_surfacevisible)
3939                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3940                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3941         }
3942 }
3943
3944 extern rtexture_t *loadingscreentexture;
3945 static void gl_main_start(void)
3946 {
3947         loadingscreentexture = NULL;
3948         r_texture_blanknormalmap = NULL;
3949         r_texture_white = NULL;
3950         r_texture_grey128 = NULL;
3951         r_texture_black = NULL;
3952         r_texture_whitecube = NULL;
3953         r_texture_normalizationcube = NULL;
3954         r_texture_fogattenuation = NULL;
3955         r_texture_fogheighttexture = NULL;
3956         r_texture_gammaramps = NULL;
3957         r_texture_numcubemaps = 0;
3958
3959         r_loaddds = r_texture_dds_load.integer != 0;
3960         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3961
3962         switch(vid.renderpath)
3963         {
3964         case RENDERPATH_GL20:
3965         case RENDERPATH_D3D9:
3966         case RENDERPATH_D3D10:
3967         case RENDERPATH_D3D11:
3968         case RENDERPATH_SOFT:
3969         case RENDERPATH_GLES2:
3970                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3971                 Cvar_SetValueQuick(&gl_combine, 1);
3972                 Cvar_SetValueQuick(&r_glsl, 1);
3973                 r_loadnormalmap = true;
3974                 r_loadgloss = true;
3975                 r_loadfog = false;
3976                 break;
3977         case RENDERPATH_GL13:
3978         case RENDERPATH_GLES1:
3979                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3980                 Cvar_SetValueQuick(&gl_combine, 1);
3981                 Cvar_SetValueQuick(&r_glsl, 0);
3982                 r_loadnormalmap = false;
3983                 r_loadgloss = false;
3984                 r_loadfog = true;
3985                 break;
3986         case RENDERPATH_GL11:
3987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3988                 Cvar_SetValueQuick(&gl_combine, 0);
3989                 Cvar_SetValueQuick(&r_glsl, 0);
3990                 r_loadnormalmap = false;
3991                 r_loadgloss = false;
3992                 r_loadfog = true;
3993                 break;
3994         }
3995
3996         R_AnimCache_Free();
3997         R_FrameData_Reset();
3998
3999         r_numqueries = 0;
4000         r_maxqueries = 0;
4001         memset(r_queries, 0, sizeof(r_queries));
4002
4003         r_qwskincache = NULL;
4004         r_qwskincache_size = 0;
4005
4006         // due to caching of texture_t references, the collision cache must be reset
4007         Collision_Cache_Reset(true);
4008
4009         // set up r_skinframe loading system for textures
4010         memset(&r_skinframe, 0, sizeof(r_skinframe));
4011         r_skinframe.loadsequence = 1;
4012         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4013
4014         r_main_texturepool = R_AllocTexturePool();
4015         R_BuildBlankTextures();
4016         R_BuildNoTexture();
4017         if (vid.support.arb_texture_cube_map)
4018         {
4019                 R_BuildWhiteCube();
4020                 R_BuildNormalizationCube();
4021         }
4022         r_texture_fogattenuation = NULL;
4023         r_texture_fogheighttexture = NULL;
4024         r_texture_gammaramps = NULL;
4025         //r_texture_fogintensity = NULL;
4026         memset(&r_fb, 0, sizeof(r_fb));
4027         r_glsl_permutation = NULL;
4028         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4029         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4030         glslshaderstring = NULL;
4031 #ifdef SUPPORTD3D
4032         r_hlsl_permutation = NULL;
4033         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4034         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4035 #endif
4036         hlslshaderstring = NULL;
4037         memset(&r_svbsp, 0, sizeof (r_svbsp));
4038
4039         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4040         r_texture_numcubemaps = 0;
4041
4042         r_refdef.fogmasktable_density = 0;
4043 }
4044
4045 static void gl_main_shutdown(void)
4046 {
4047         R_AnimCache_Free();
4048         R_FrameData_Reset();
4049
4050         R_Main_FreeViewCache();
4051
4052         switch(vid.renderpath)
4053         {
4054         case RENDERPATH_GL11:
4055         case RENDERPATH_GL13:
4056         case RENDERPATH_GL20:
4057         case RENDERPATH_GLES1:
4058         case RENDERPATH_GLES2:
4059 #ifdef GL_SAMPLES_PASSED_ARB
4060                 if (r_maxqueries)
4061                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4062 #endif
4063                 break;
4064         case RENDERPATH_D3D9:
4065                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4066                 break;
4067         case RENDERPATH_D3D10:
4068                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4069                 break;
4070         case RENDERPATH_D3D11:
4071                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072                 break;
4073         case RENDERPATH_SOFT:
4074                 break;
4075         }
4076
4077         r_numqueries = 0;
4078         r_maxqueries = 0;
4079         memset(r_queries, 0, sizeof(r_queries));
4080
4081         r_qwskincache = NULL;
4082         r_qwskincache_size = 0;
4083
4084         // clear out the r_skinframe state
4085         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4086         memset(&r_skinframe, 0, sizeof(r_skinframe));
4087
4088         if (r_svbsp.nodes)
4089                 Mem_Free(r_svbsp.nodes);
4090         memset(&r_svbsp, 0, sizeof (r_svbsp));
4091         R_FreeTexturePool(&r_main_texturepool);
4092         loadingscreentexture = NULL;
4093         r_texture_blanknormalmap = NULL;
4094         r_texture_white = NULL;
4095         r_texture_grey128 = NULL;
4096         r_texture_black = NULL;
4097         r_texture_whitecube = NULL;
4098         r_texture_normalizationcube = NULL;
4099         r_texture_fogattenuation = NULL;
4100         r_texture_fogheighttexture = NULL;
4101         r_texture_gammaramps = NULL;
4102         r_texture_numcubemaps = 0;
4103         //r_texture_fogintensity = NULL;
4104         memset(&r_fb, 0, sizeof(r_fb));
4105         R_GLSL_Restart_f();
4106
4107         r_glsl_permutation = NULL;
4108         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4109         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4110         glslshaderstring = NULL;
4111 #ifdef SUPPORTD3D
4112         r_hlsl_permutation = NULL;
4113         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4114         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4115 #endif
4116         hlslshaderstring = NULL;
4117 }
4118
4119 static void gl_main_newmap(void)
4120 {
4121         // FIXME: move this code to client
4122         char *entities, entname[MAX_QPATH];
4123         if (r_qwskincache)
4124                 Mem_Free(r_qwskincache);
4125         r_qwskincache = NULL;
4126         r_qwskincache_size = 0;
4127         if (cl.worldmodel)
4128         {
4129                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4130                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4131                 {
4132                         CL_ParseEntityLump(entities);
4133                         Mem_Free(entities);
4134                         return;
4135                 }
4136                 if (cl.worldmodel->brush.entities)
4137                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4138         }
4139         R_Main_FreeViewCache();
4140
4141         R_FrameData_Reset();
4142 }
4143
4144 void GL_Main_Init(void)
4145 {
4146         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4147
4148         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4149         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4150         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4151         if (gamemode == GAME_NEHAHRA)
4152         {
4153                 Cvar_RegisterVariable (&gl_fogenable);
4154                 Cvar_RegisterVariable (&gl_fogdensity);
4155                 Cvar_RegisterVariable (&gl_fogred);
4156                 Cvar_RegisterVariable (&gl_foggreen);
4157                 Cvar_RegisterVariable (&gl_fogblue);
4158                 Cvar_RegisterVariable (&gl_fogstart);
4159                 Cvar_RegisterVariable (&gl_fogend);
4160                 Cvar_RegisterVariable (&gl_skyclip);
4161         }
4162         Cvar_RegisterVariable(&r_motionblur);
4163         Cvar_RegisterVariable(&r_damageblur);
4164         Cvar_RegisterVariable(&r_motionblur_averaging);
4165         Cvar_RegisterVariable(&r_motionblur_randomize);
4166         Cvar_RegisterVariable(&r_motionblur_minblur);
4167         Cvar_RegisterVariable(&r_motionblur_maxblur);
4168         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4169         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4170         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4171         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4172         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4173         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4174         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4175         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4176         Cvar_RegisterVariable(&r_equalize_entities_by);
4177         Cvar_RegisterVariable(&r_equalize_entities_to);
4178         Cvar_RegisterVariable(&r_depthfirst);
4179         Cvar_RegisterVariable(&r_useinfinitefarclip);
4180         Cvar_RegisterVariable(&r_farclip_base);
4181         Cvar_RegisterVariable(&r_farclip_world);
4182         Cvar_RegisterVariable(&r_nearclip);
4183         Cvar_RegisterVariable(&r_deformvertexes);
4184         Cvar_RegisterVariable(&r_transparent);
4185         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4186         Cvar_RegisterVariable(&r_showoverdraw);
4187         Cvar_RegisterVariable(&r_showbboxes);
4188         Cvar_RegisterVariable(&r_showsurfaces);
4189         Cvar_RegisterVariable(&r_showtris);
4190         Cvar_RegisterVariable(&r_shownormals);
4191         Cvar_RegisterVariable(&r_showlighting);
4192         Cvar_RegisterVariable(&r_showshadowvolumes);
4193         Cvar_RegisterVariable(&r_showcollisionbrushes);
4194         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4195         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4196         Cvar_RegisterVariable(&r_showdisabledepthtest);
4197         Cvar_RegisterVariable(&r_drawportals);
4198         Cvar_RegisterVariable(&r_drawentities);
4199         Cvar_RegisterVariable(&r_draw2d);
4200         Cvar_RegisterVariable(&r_drawworld);
4201         Cvar_RegisterVariable(&r_cullentities_trace);
4202         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4203         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4204         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4205         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4206         Cvar_RegisterVariable(&r_sortentities);
4207         Cvar_RegisterVariable(&r_drawviewmodel);
4208         Cvar_RegisterVariable(&r_drawexteriormodel);
4209         Cvar_RegisterVariable(&r_speeds);
4210         Cvar_RegisterVariable(&r_fullbrights);
4211         Cvar_RegisterVariable(&r_wateralpha);
4212         Cvar_RegisterVariable(&r_dynamic);
4213         Cvar_RegisterVariable(&r_fakelight);
4214         Cvar_RegisterVariable(&r_fakelight_intensity);
4215         Cvar_RegisterVariable(&r_fullbright);
4216         Cvar_RegisterVariable(&r_shadows);
4217         Cvar_RegisterVariable(&r_shadows_darken);
4218         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4219         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4220         Cvar_RegisterVariable(&r_shadows_throwdistance);
4221         Cvar_RegisterVariable(&r_shadows_throwdirection);
4222         Cvar_RegisterVariable(&r_shadows_focus);
4223         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4224         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4225         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4226         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4227         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4228         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4229         Cvar_RegisterVariable(&r_fog_exp2);
4230         Cvar_RegisterVariable(&r_fog_clear);
4231         Cvar_RegisterVariable(&r_drawfog);
4232         Cvar_RegisterVariable(&r_transparentdepthmasking);
4233         Cvar_RegisterVariable(&r_transparent_sortmindist);
4234         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4235         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4236         Cvar_RegisterVariable(&r_texture_dds_load);
4237         Cvar_RegisterVariable(&r_texture_dds_save);
4238         Cvar_RegisterVariable(&r_textureunits);
4239         Cvar_RegisterVariable(&gl_combine);
4240         Cvar_RegisterVariable(&r_viewfbo);
4241         Cvar_RegisterVariable(&r_viewscale);
4242         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4247         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4248         Cvar_RegisterVariable(&r_glsl);
4249         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4257         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4258         Cvar_RegisterVariable(&r_glsl_postprocess);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4266         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4267
4268         Cvar_RegisterVariable(&r_water);
4269         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4270         Cvar_RegisterVariable(&r_water_clippingplanebias);
4271         Cvar_RegisterVariable(&r_water_refractdistort);
4272         Cvar_RegisterVariable(&r_water_reflectdistort);
4273         Cvar_RegisterVariable(&r_water_scissormode);
4274         Cvar_RegisterVariable(&r_water_lowquality);
4275         Cvar_RegisterVariable(&r_water_hideplayer);
4276         Cvar_RegisterVariable(&r_water_fbo);
4277
4278         Cvar_RegisterVariable(&r_lerpsprites);
4279         Cvar_RegisterVariable(&r_lerpmodels);
4280         Cvar_RegisterVariable(&r_lerplightstyles);
4281         Cvar_RegisterVariable(&r_waterscroll);
4282         Cvar_RegisterVariable(&r_bloom);
4283         Cvar_RegisterVariable(&r_bloom_colorscale);
4284         Cvar_RegisterVariable(&r_bloom_brighten);
4285         Cvar_RegisterVariable(&r_bloom_blur);
4286         Cvar_RegisterVariable(&r_bloom_resolution);
4287         Cvar_RegisterVariable(&r_bloom_colorexponent);
4288         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4289         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4290         Cvar_RegisterVariable(&r_hdr_glowintensity);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4298         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4299         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4300         Cvar_RegisterVariable(&developer_texturelogging);
4301         Cvar_RegisterVariable(&gl_lightmaps);
4302         Cvar_RegisterVariable(&r_test);
4303         Cvar_RegisterVariable(&r_glsl_saturation);
4304         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4305         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4306         Cvar_RegisterVariable(&r_framedatasize);
4307         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4308                 Cvar_SetValue("r_fullbrights", 0);
4309         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4310 }
4311
4312 void Render_Init(void)
4313 {
4314         gl_backend_init();
4315         R_Textures_Init();
4316         GL_Main_Init();
4317         Font_Init();
4318         GL_Draw_Init();
4319         R_Shadow_Init();
4320         R_Sky_Init();
4321         GL_Surf_Init();
4322         Sbar_Init();
4323         R_Particles_Init();
4324         R_Explosion_Init();
4325         R_LightningBeams_Init();
4326         Mod_RenderInit();
4327 }
4328
4329 /*
4330 ===============
4331 GL_Init
4332 ===============
4333 */
4334 #ifndef USE_GLES2
4335 extern char *ENGINE_EXTENSIONS;
4336 void GL_Init (void)
4337 {
4338         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4339         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4340         gl_version = (const char *)qglGetString(GL_VERSION);
4341         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4342
4343         if (!gl_extensions)
4344                 gl_extensions = "";
4345         if (!gl_platformextensions)
4346                 gl_platformextensions = "";
4347
4348         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4349         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4350         Con_Printf("GL_VERSION: %s\n", gl_version);
4351         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4352         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4353
4354         VID_CheckExtensions();
4355
4356         // LordHavoc: report supported extensions
4357         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4358
4359         // clear to black (loading plaque will be seen over this)
4360         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4361 }
4362 #endif
4363
4364 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4365 {
4366         int i;
4367         mplane_t *p;
4368         if (r_trippy.integer)
4369                 return false;
4370         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4371         {
4372                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4373                 if (i == 4)
4374                         continue;
4375                 p = r_refdef.view.frustum + i;
4376                 switch(p->signbits)
4377                 {
4378                 default:
4379                 case 0:
4380                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4381                                 return true;
4382                         break;
4383                 case 1:
4384                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4385                                 return true;
4386                         break;
4387                 case 2:
4388                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 3:
4392                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 case 4:
4396                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 5:
4400                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 6:
4404                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 7:
4408                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 }
4412         }
4413         return false;
4414 }
4415
4416 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4417 {
4418         int i;
4419         const mplane_t *p;
4420         if (r_trippy.integer)
4421                 return false;
4422         for (i = 0;i < numplanes;i++)
4423         {
4424                 p = planes + i;
4425                 switch(p->signbits)
4426                 {
4427                 default:
4428                 case 0:
4429                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4430                                 return true;
4431                         break;
4432                 case 1:
4433                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4434                                 return true;
4435                         break;
4436                 case 2:
4437                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 3:
4441                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 4:
4445                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 5:
4449                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 6:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 7:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 }
4461         }
4462         return false;
4463 }
4464
4465 //==================================================================================
4466
4467 // LordHavoc: this stores temporary data used within the same frame
4468
4469 typedef struct r_framedata_mem_s
4470 {
4471         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4472         size_t size; // how much usable space
4473         size_t current; // how much space in use
4474         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4475         size_t wantedsize; // how much space was allocated
4476         unsigned char *data; // start of real data (16byte aligned)
4477 }
4478 r_framedata_mem_t;
4479
4480 static r_framedata_mem_t *r_framedata_mem;
4481
4482 void R_FrameData_Reset(void)
4483 {
4484         while (r_framedata_mem)
4485         {
4486                 r_framedata_mem_t *next = r_framedata_mem->purge;
4487                 Mem_Free(r_framedata_mem);
4488                 r_framedata_mem = next;
4489         }
4490 }
4491
4492 static void R_FrameData_Resize(void)
4493 {
4494         size_t wantedsize;
4495         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4496         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4497         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4498         {
4499                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4500                 newmem->wantedsize = wantedsize;
4501                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4502                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4503                 newmem->current = 0;
4504                 newmem->mark = 0;
4505                 newmem->purge = r_framedata_mem;
4506                 r_framedata_mem = newmem;
4507         }
4508 }
4509
4510 void R_FrameData_NewFrame(void)
4511 {
4512         R_FrameData_Resize();
4513         if (!r_framedata_mem)
4514                 return;
4515         // if we ran out of space on the last frame, free the old memory now
4516         while (r_framedata_mem->purge)
4517         {
4518                 // repeatedly remove the second item in the list, leaving only head
4519                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4520                 Mem_Free(r_framedata_mem->purge);
4521                 r_framedata_mem->purge = next;
4522         }
4523         // reset the current mem pointer
4524         r_framedata_mem->current = 0;
4525         r_framedata_mem->mark = 0;
4526 }
4527
4528 void *R_FrameData_Alloc(size_t size)
4529 {
4530         void *data;
4531
4532         // align to 16 byte boundary - the data pointer is already aligned, so we
4533         // only need to ensure the size of every allocation is also aligned
4534         size = (size + 15) & ~15;
4535
4536         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4537         {
4538                 // emergency - we ran out of space, allocate more memory
4539                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4540                 R_FrameData_Resize();
4541         }
4542
4543         data = r_framedata_mem->data + r_framedata_mem->current;
4544         r_framedata_mem->current += size;
4545
4546         // count the usage for stats
4547         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4548         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4549
4550         return (void *)data;
4551 }
4552
4553 void *R_FrameData_Store(size_t size, void *data)
4554 {
4555         void *d = R_FrameData_Alloc(size);
4556         if (d && data)
4557                 memcpy(d, data, size);
4558         return d;
4559 }
4560
4561 void R_FrameData_SetMark(void)
4562 {
4563         if (!r_framedata_mem)
4564                 return;
4565         r_framedata_mem->mark = r_framedata_mem->current;
4566 }
4567
4568 void R_FrameData_ReturnToMark(void)
4569 {
4570         if (!r_framedata_mem)
4571                 return;
4572         r_framedata_mem->current = r_framedata_mem->mark;
4573 }
4574
4575 //==================================================================================
4576
4577 // LordHavoc: animcache originally written by Echon, rewritten since then
4578
4579 /**
4580  * Animation cache prevents re-generating mesh data for an animated model
4581  * multiple times in one frame for lighting, shadowing, reflections, etc.
4582  */
4583
4584 void R_AnimCache_Free(void)
4585 {
4586 }
4587
4588 void R_AnimCache_ClearCache(void)
4589 {
4590         int i;
4591         entity_render_t *ent;
4592
4593         for (i = 0;i < r_refdef.scene.numentities;i++)
4594         {
4595                 ent = r_refdef.scene.entities[i];
4596                 ent->animcache_vertex3f = NULL;
4597                 ent->animcache_normal3f = NULL;
4598                 ent->animcache_svector3f = NULL;
4599                 ent->animcache_tvector3f = NULL;
4600                 ent->animcache_vertexmesh = NULL;
4601                 ent->animcache_vertex3fbuffer = NULL;
4602                 ent->animcache_vertexmeshbuffer = NULL;
4603         }
4604 }
4605
4606 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4607 {
4608         int i;
4609
4610         // check if we need the meshbuffers
4611         if (!vid.useinterleavedarrays)
4612                 return;
4613
4614         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4615                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4616         // TODO: upload vertex3f buffer?
4617         if (ent->animcache_vertexmesh)
4618         {
4619                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4620                 for (i = 0;i < numvertices;i++)
4621                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4622                 if (ent->animcache_svector3f)
4623                         for (i = 0;i < numvertices;i++)
4624                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4625                 if (ent->animcache_tvector3f)
4626                         for (i = 0;i < numvertices;i++)
4627                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4628                 if (ent->animcache_normal3f)
4629                         for (i = 0;i < numvertices;i++)
4630                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4631                 // TODO: upload vertexmeshbuffer?
4632         }
4633 }
4634
4635 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4636 {
4637         dp_model_t *model = ent->model;
4638         int numvertices;
4639         // see if it's already cached this frame
4640         if (ent->animcache_vertex3f)
4641         {
4642                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4643                 if (wantnormals || wanttangents)
4644                 {
4645                         if (ent->animcache_normal3f)
4646                                 wantnormals = false;
4647                         if (ent->animcache_svector3f)
4648                                 wanttangents = false;
4649                         if (wantnormals || wanttangents)
4650                         {
4651                                 numvertices = model->surfmesh.num_vertices;
4652                                 if (wantnormals)
4653                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4654                                 if (wanttangents)
4655                                 {
4656                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                                 }
4659                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4660                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4661                         }
4662                 }
4663         }
4664         else
4665         {
4666                 // see if this ent is worth caching
4667                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4668                         return false;
4669                 // get some memory for this entity and generate mesh data
4670                 numvertices = model->surfmesh.num_vertices;
4671                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4672                 if (wantnormals)
4673                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4674                 if (wanttangents)
4675                 {
4676                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4678                 }
4679                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4680                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4681         }
4682         return true;
4683 }
4684
4685 void R_AnimCache_CacheVisibleEntities(void)
4686 {
4687         int i;
4688         qboolean wantnormals = true;
4689         qboolean wanttangents = !r_showsurfaces.integer;
4690
4691         switch(vid.renderpath)
4692         {
4693         case RENDERPATH_GL20:
4694         case RENDERPATH_D3D9:
4695         case RENDERPATH_D3D10:
4696         case RENDERPATH_D3D11:
4697         case RENDERPATH_GLES2:
4698                 break;
4699         case RENDERPATH_GL11:
4700         case RENDERPATH_GL13:
4701         case RENDERPATH_GLES1:
4702                 wanttangents = false;
4703                 break;
4704         case RENDERPATH_SOFT:
4705                 break;
4706         }
4707
4708         if (r_shownormals.integer)
4709                 wanttangents = wantnormals = true;
4710
4711         // TODO: thread this
4712         // NOTE: R_PrepareRTLights() also caches entities
4713
4714         for (i = 0;i < r_refdef.scene.numentities;i++)
4715                 if (r_refdef.viewcache.entityvisible[i])
4716                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4717 }
4718
4719 //==================================================================================
4720
4721 extern cvar_t r_overheadsprites_pushback;
4722
4723 static void R_View_UpdateEntityLighting (void)
4724 {
4725         int i;
4726         entity_render_t *ent;
4727         vec3_t tempdiffusenormal, avg;
4728         vec_t f, fa, fd, fdd;
4729         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4730
4731         for (i = 0;i < r_refdef.scene.numentities;i++)
4732         {
4733                 ent = r_refdef.scene.entities[i];
4734
4735                 // skip unseen models and models that updated by CSQC
4736                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4737                         continue;
4738
4739                 // skip bsp models
4740                 if (ent->model && ent->model->brush.num_leafs)
4741                 {
4742                         // TODO: use modellight for r_ambient settings on world?
4743                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4744                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4745                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4746                         continue;
4747                 }
4748
4749                 // fetch the lighting from the worldmodel data
4750                 VectorClear(ent->modellight_ambient);
4751                 VectorClear(ent->modellight_diffuse);
4752                 VectorClear(tempdiffusenormal);
4753                 if (ent->flags & RENDER_LIGHT)
4754                 {
4755                         vec3_t org;
4756                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4757
4758                         // complete lightning for lit sprites
4759                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4760                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4761                         {
4762                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4763                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4764                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4765                         }
4766                         else
4767                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4768
4769                         if(ent->flags & RENDER_EQUALIZE)
4770                         {
4771                                 // first fix up ambient lighting...
4772                                 if(r_equalize_entities_minambient.value > 0)
4773                                 {
4774                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4775                                         if(fd > 0)
4776                                         {
4777                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4778                                                 if(fa < r_equalize_entities_minambient.value * fd)
4779                                                 {
4780                                                         // solve:
4781                                                         //   fa'/fd' = minambient
4782                                                         //   fa'+0.25*fd' = fa+0.25*fd
4783                                                         //   ...
4784                                                         //   fa' = fd' * minambient
4785                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4786                                                         //   ...
4787                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4788                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4789                                                         //   ...
4790                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4791                                                         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
4792                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4793                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4794                                                 }
4795                                         }
4796                                 }
4797
4798                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4799                                 {
4800                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4801                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4802                                         f = fa + 0.25 * fd;
4803                                         if(f > 0)
4804                                         {
4805                                                 // adjust brightness and saturation to target
4806                                                 avg[0] = avg[1] = avg[2] = fa / f;
4807                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4808                                                 avg[0] = avg[1] = avg[2] = fd / f;
4809                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4810                                         }
4811                                 }
4812                         }
4813                 }
4814                 else // highly rare
4815                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4816
4817                 // move the light direction into modelspace coordinates for lighting code
4818                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4819                 if(VectorLength2(ent->modellight_lightdir) == 0)
4820                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4821                 VectorNormalize(ent->modellight_lightdir);
4822         }
4823 }
4824
4825 #define MAX_LINEOFSIGHTTRACES 64
4826
4827 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4828 {
4829         int i;
4830         vec3_t boxmins, boxmaxs;
4831         vec3_t start;
4832         vec3_t end;
4833         dp_model_t *model = r_refdef.scene.worldmodel;
4834
4835         if (!model || !model->brush.TraceLineOfSight)
4836                 return true;
4837
4838         // expand the box a little
4839         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4840         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4841         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4842         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4843         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4844         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4845
4846         // return true if eye is inside enlarged box
4847         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4848                 return true;
4849
4850         // try center
4851         VectorCopy(eye, start);
4852         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4853         if (model->brush.TraceLineOfSight(model, start, end))
4854                 return true;
4855
4856         // try various random positions
4857         for (i = 0;i < numsamples;i++)
4858         {
4859                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4860                 if (model->brush.TraceLineOfSight(model, start, end))
4861                         return true;
4862         }
4863
4864         return false;
4865 }
4866
4867
4868 static void R_View_UpdateEntityVisible (void)
4869 {
4870         int i;
4871         int renderimask;
4872         int samples;
4873         entity_render_t *ent;
4874
4875         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4876                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4877                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4878                 :                                                          RENDER_EXTERIORMODEL;
4879         if (!r_drawviewmodel.integer)
4880                 renderimask |= RENDER_VIEWMODEL;
4881         if (!r_drawexteriormodel.integer)
4882                 renderimask |= RENDER_EXTERIORMODEL;
4883         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4884         {
4885                 // worldmodel can check visibility
4886                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4887                 for (i = 0;i < r_refdef.scene.numentities;i++)
4888                 {
4889                         ent = r_refdef.scene.entities[i];
4890                         if (!(ent->flags & renderimask))
4891                         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)))
4892                         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))
4893                                 r_refdef.viewcache.entityvisible[i] = true;
4894                 }
4895         }
4896         else
4897         {
4898                 // no worldmodel or it can't check visibility
4899                 for (i = 0;i < r_refdef.scene.numentities;i++)
4900                 {
4901                         ent = r_refdef.scene.entities[i];
4902                         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));
4903                 }
4904         }
4905         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4906                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4907         {
4908                 for (i = 0;i < r_refdef.scene.numentities;i++)
4909                 {
4910                         if (!r_refdef.viewcache.entityvisible[i])
4911                                 continue;
4912                         ent = r_refdef.scene.entities[i];
4913                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4914                         {
4915                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4916                                 if (samples < 0)
4917                                         continue; // temp entities do pvs only
4918                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4919                                         ent->last_trace_visibility = realtime;
4920                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4921                                         r_refdef.viewcache.entityvisible[i] = 0;
4922                         }
4923                 }
4924         }
4925 }
4926
4927 /// only used if skyrendermasked, and normally returns false
4928 static int R_DrawBrushModelsSky (void)
4929 {
4930         int i, sky;
4931         entity_render_t *ent;
4932
4933         sky = false;
4934         for (i = 0;i < r_refdef.scene.numentities;i++)
4935         {
4936                 if (!r_refdef.viewcache.entityvisible[i])
4937                         continue;
4938                 ent = r_refdef.scene.entities[i];
4939                 if (!ent->model || !ent->model->DrawSky)
4940                         continue;
4941                 ent->model->DrawSky(ent);
4942                 sky = true;
4943         }
4944         return sky;
4945 }
4946
4947 static void R_DrawNoModel(entity_render_t *ent);
4948 static void R_DrawModels(void)
4949 {
4950         int i;
4951         entity_render_t *ent;
4952
4953         for (i = 0;i < r_refdef.scene.numentities;i++)
4954         {
4955                 if (!r_refdef.viewcache.entityvisible[i])
4956                         continue;
4957                 ent = r_refdef.scene.entities[i];
4958                 r_refdef.stats.entities++;
4959                 /*
4960                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4961                 {
4962                         vec3_t f, l, u, o;
4963                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4964                         Con_Printf("R_DrawModels\n");
4965                         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]);
4966                         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);
4967                         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);
4968                 }
4969                 */
4970                 if (ent->model && ent->model->Draw != NULL)
4971                         ent->model->Draw(ent);
4972                 else
4973                         R_DrawNoModel(ent);
4974         }
4975 }
4976
4977 static void R_DrawModelsDepth(void)
4978 {
4979         int i;
4980         entity_render_t *ent;
4981
4982         for (i = 0;i < r_refdef.scene.numentities;i++)
4983         {
4984                 if (!r_refdef.viewcache.entityvisible[i])
4985                         continue;
4986                 ent = r_refdef.scene.entities[i];
4987                 if (ent->model && ent->model->DrawDepth != NULL)
4988                         ent->model->DrawDepth(ent);
4989         }
4990 }
4991
4992 static void R_DrawModelsDebug(void)
4993 {
4994         int i;
4995         entity_render_t *ent;
4996
4997         for (i = 0;i < r_refdef.scene.numentities;i++)
4998         {
4999                 if (!r_refdef.viewcache.entityvisible[i])
5000                         continue;
5001                 ent = r_refdef.scene.entities[i];
5002                 if (ent->model && ent->model->DrawDebug != NULL)
5003                         ent->model->DrawDebug(ent);
5004         }
5005 }
5006
5007 static void R_DrawModelsAddWaterPlanes(void)
5008 {
5009         int i;
5010         entity_render_t *ent;
5011
5012         for (i = 0;i < r_refdef.scene.numentities;i++)
5013         {
5014                 if (!r_refdef.viewcache.entityvisible[i])
5015                         continue;
5016                 ent = r_refdef.scene.entities[i];
5017                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5018                         ent->model->DrawAddWaterPlanes(ent);
5019         }
5020 }
5021
5022 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}};
5023
5024 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5025 {
5026         if (r_hdr_irisadaptation.integer)
5027         {
5028                 vec3_t p;
5029                 vec3_t ambient;
5030                 vec3_t diffuse;
5031                 vec3_t diffusenormal;
5032                 vec3_t forward;
5033                 vec_t brightness = 0.0f;
5034                 vec_t goal;
5035                 vec_t current;
5036                 vec_t d;
5037                 int c;
5038                 VectorCopy(r_refdef.view.forward, forward);
5039                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5040                 {
5041                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5042                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5043                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5044                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5045                         d = DotProduct(forward, diffusenormal);
5046                         brightness += VectorLength(ambient);
5047                         if (d > 0)
5048                                 brightness += d * VectorLength(diffuse);
5049                 }
5050                 brightness *= 1.0f / c;
5051                 brightness += 0.00001f; // make sure it's never zero
5052                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5053                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5054                 current = r_hdr_irisadaptation_value.value;
5055                 if (current < goal)
5056                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5057                 else if (current > goal)
5058                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5059                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5060                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5061         }
5062         else if (r_hdr_irisadaptation_value.value != 1.0f)
5063                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5064 }
5065
5066 static void R_View_SetFrustum(const int *scissor)
5067 {
5068         int i;
5069         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5070         vec3_t forward, left, up, origin, v;
5071
5072         if(scissor)
5073         {
5074                 // flipped x coordinates (because x points left here)
5075                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5076                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5077
5078                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5079                 switch(vid.renderpath)
5080                 {
5081                         case RENDERPATH_D3D9:
5082                         case RENDERPATH_D3D10:
5083                         case RENDERPATH_D3D11:
5084                                 // non-flipped y coordinates
5085                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5086                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5087                                 break;
5088                         case RENDERPATH_SOFT:
5089                         case RENDERPATH_GL11:
5090                         case RENDERPATH_GL13:
5091                         case RENDERPATH_GL20:
5092                         case RENDERPATH_GLES1:
5093                         case RENDERPATH_GLES2:
5094                                 // non-flipped y coordinates
5095                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5096                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5097                                 break;
5098                 }
5099         }
5100
5101         // we can't trust r_refdef.view.forward and friends in reflected scenes
5102         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5103
5104 #if 0
5105         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5106         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5107         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5108         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5109         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5110         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5111         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5112         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5113         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5114         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5115         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5116         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5117 #endif
5118
5119 #if 0
5120         zNear = r_refdef.nearclip;
5121         nudge = 1.0 - 1.0 / (1<<23);
5122         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5123         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5124         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5125         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5126         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5127         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5128         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5129         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5130 #endif
5131
5132
5133
5134 #if 0
5135         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5136         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5137         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5138         r_refdef.view.frustum[0].dist = m[15] - m[12];
5139
5140         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5141         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5142         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5143         r_refdef.view.frustum[1].dist = m[15] + m[12];
5144
5145         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5146         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5147         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5148         r_refdef.view.frustum[2].dist = m[15] - m[13];
5149
5150         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5151         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5152         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5153         r_refdef.view.frustum[3].dist = m[15] + m[13];
5154
5155         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5156         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5157         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5158         r_refdef.view.frustum[4].dist = m[15] - m[14];
5159
5160         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5161         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5162         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5163         r_refdef.view.frustum[5].dist = m[15] + m[14];
5164 #endif
5165
5166         if (r_refdef.view.useperspective)
5167         {
5168                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5169                 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]);
5170                 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]);
5171                 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]);
5172                 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]);
5173
5174                 // then the normals from the corners relative to origin
5175                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5176                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5177                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5178                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5179
5180                 // in a NORMAL view, forward cross left == up
5181                 // in a REFLECTED view, forward cross left == down
5182                 // so our cross products above need to be adjusted for a left handed coordinate system
5183                 CrossProduct(forward, left, v);
5184                 if(DotProduct(v, up) < 0)
5185                 {
5186                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5187                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5188                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5189                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5190                 }
5191
5192                 // Leaving those out was a mistake, those were in the old code, and they
5193                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5194                 // I couldn't reproduce it after adding those normalizations. --blub
5195                 VectorNormalize(r_refdef.view.frustum[0].normal);
5196                 VectorNormalize(r_refdef.view.frustum[1].normal);
5197                 VectorNormalize(r_refdef.view.frustum[2].normal);
5198                 VectorNormalize(r_refdef.view.frustum[3].normal);
5199
5200                 // make the corners absolute
5201                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5202                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5203                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5204                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5205
5206                 // one more normal
5207                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5208
5209                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5210                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5211                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5212                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5213                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5214         }
5215         else
5216         {
5217                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5218                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5219                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5220                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5221                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5222                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5223                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5224                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5225                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5226                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5227         }
5228         r_refdef.view.numfrustumplanes = 5;
5229
5230         if (r_refdef.view.useclipplane)
5231         {
5232                 r_refdef.view.numfrustumplanes = 6;
5233                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5234         }
5235
5236         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5237                 PlaneClassify(r_refdef.view.frustum + i);
5238
5239         // LordHavoc: note to all quake engine coders, Quake had a special case
5240         // for 90 degrees which assumed a square view (wrong), so I removed it,
5241         // Quake2 has it disabled as well.
5242
5243         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5244         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5245         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5246         //PlaneClassify(&frustum[0]);
5247
5248         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5249         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5250         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5251         //PlaneClassify(&frustum[1]);
5252
5253         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5254         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5255         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5256         //PlaneClassify(&frustum[2]);
5257
5258         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5259         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5260         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5261         //PlaneClassify(&frustum[3]);
5262
5263         // nearclip plane
5264         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5265         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5266         //PlaneClassify(&frustum[4]);
5267 }
5268
5269 static void R_View_UpdateWithScissor(const int *myscissor)
5270 {
5271         R_Main_ResizeViewCache();
5272         R_View_SetFrustum(myscissor);
5273         R_View_WorldVisibility(r_refdef.view.useclipplane);
5274         R_View_UpdateEntityVisible();
5275         R_View_UpdateEntityLighting();
5276         R_AnimCache_CacheVisibleEntities();
5277 }
5278
5279 static void R_View_Update(void)
5280 {
5281         R_Main_ResizeViewCache();
5282         R_View_SetFrustum(NULL);
5283         R_View_WorldVisibility(r_refdef.view.useclipplane);
5284         R_View_UpdateEntityVisible();
5285         R_View_UpdateEntityLighting();
5286         R_AnimCache_CacheVisibleEntities();
5287 }
5288
5289 float viewscalefpsadjusted = 1.0f;
5290
5291 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5292 {
5293         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5294         scale = bound(0.03125f, scale, 1.0f);
5295         *outwidth = (int)ceil(width * scale);
5296         *outheight = (int)ceil(height * scale);
5297 }
5298
5299 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5300 {
5301         const float *customclipplane = NULL;
5302         float plane[4];
5303         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5304         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5305         {
5306                 // LordHavoc: couldn't figure out how to make this approach the
5307                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5308                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5309                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5310                         dist = r_refdef.view.clipplane.dist;
5311                 plane[0] = r_refdef.view.clipplane.normal[0];
5312                 plane[1] = r_refdef.view.clipplane.normal[1];
5313                 plane[2] = r_refdef.view.clipplane.normal[2];
5314                 plane[3] = -dist;
5315                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5316         }
5317
5318         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5319         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5320
5321         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5322         if (!r_refdef.view.useperspective)
5323                 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);
5324         else if (vid.stencil && r_useinfinitefarclip.integer)
5325                 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);
5326         else
5327                 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);
5328         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5329         R_SetViewport(&r_refdef.view.viewport);
5330         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5331         {
5332                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5333                 float screenplane[4];
5334                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5335                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5336                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5337                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5338                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5339         }
5340 }
5341
5342 void R_EntityMatrix(const matrix4x4_t *matrix)
5343 {
5344         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5345         {
5346                 gl_modelmatrixchanged = false;
5347                 gl_modelmatrix = *matrix;
5348                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5349                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5350                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5351                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5352                 CHECKGLERROR
5353                 switch(vid.renderpath)
5354                 {
5355                 case RENDERPATH_D3D9:
5356 #ifdef SUPPORTD3D
5357                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5358                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5359 #endif
5360                         break;
5361                 case RENDERPATH_D3D10:
5362                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5363                         break;
5364                 case RENDERPATH_D3D11:
5365                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5366                         break;
5367                 case RENDERPATH_GL11:
5368                 case RENDERPATH_GL13:
5369                 case RENDERPATH_GLES1:
5370                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5371                         break;
5372                 case RENDERPATH_SOFT:
5373                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5374                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5375                         break;
5376                 case RENDERPATH_GL20:
5377                 case RENDERPATH_GLES2:
5378                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5379                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5380                         break;
5381                 }
5382         }
5383 }
5384
5385 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5386 {
5387         r_viewport_t viewport;
5388         DrawQ_Finish();
5389
5390         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5391         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, 1, 1, -10, 100, NULL);
5392         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5393         R_SetViewport(&viewport);
5394         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5395         GL_Color(1, 1, 1, 1);
5396         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5397         GL_BlendFunc(GL_ONE, GL_ZERO);
5398         GL_ScissorTest(false);
5399         GL_DepthMask(false);
5400         GL_DepthRange(0, 1);
5401         GL_DepthTest(false);
5402         GL_DepthFunc(GL_LEQUAL);
5403         R_EntityMatrix(&identitymatrix);
5404         R_Mesh_ResetTextureState();
5405         GL_PolygonOffset(0, 0);
5406         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5407         switch(vid.renderpath)
5408         {
5409         case RENDERPATH_GL11:
5410         case RENDERPATH_GL13:
5411         case RENDERPATH_GL20:
5412         case RENDERPATH_GLES1:
5413         case RENDERPATH_GLES2:
5414                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5415                 break;
5416         case RENDERPATH_D3D9:
5417         case RENDERPATH_D3D10:
5418         case RENDERPATH_D3D11:
5419         case RENDERPATH_SOFT:
5420                 break;
5421         }
5422         GL_CullFace(GL_NONE);
5423 }
5424
5425 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5426 {
5427         DrawQ_Finish();
5428
5429         R_SetupView(true, fbo, depthtexture, colortexture);
5430         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5431         GL_Color(1, 1, 1, 1);
5432         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5433         GL_BlendFunc(GL_ONE, GL_ZERO);
5434         GL_ScissorTest(true);
5435         GL_DepthMask(true);
5436         GL_DepthRange(0, 1);
5437         GL_DepthTest(true);
5438         GL_DepthFunc(GL_LEQUAL);
5439         R_EntityMatrix(&identitymatrix);
5440         R_Mesh_ResetTextureState();
5441         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5442         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5443         switch(vid.renderpath)
5444         {
5445         case RENDERPATH_GL11:
5446         case RENDERPATH_GL13:
5447         case RENDERPATH_GL20:
5448         case RENDERPATH_GLES1:
5449         case RENDERPATH_GLES2:
5450                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5451                 break;
5452         case RENDERPATH_D3D9:
5453         case RENDERPATH_D3D10:
5454         case RENDERPATH_D3D11:
5455         case RENDERPATH_SOFT:
5456                 break;
5457         }
5458         GL_CullFace(r_refdef.view.cullface_back);
5459 }
5460
5461 /*
5462 ================
5463 R_RenderView_UpdateViewVectors
5464 ================
5465 */
5466 static void R_RenderView_UpdateViewVectors(void)
5467 {
5468         // break apart the view matrix into vectors for various purposes
5469         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5470         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5471         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5472         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5473         // make an inverted copy of the view matrix for tracking sprites
5474         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5475 }
5476
5477 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5478 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5479
5480 static void R_Water_StartFrame(void)
5481 {
5482         int i;
5483         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5484         r_waterstate_waterplane_t *p;
5485         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5486
5487         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5488                 return;
5489
5490         switch(vid.renderpath)
5491         {
5492         case RENDERPATH_GL20:
5493         case RENDERPATH_D3D9:
5494         case RENDERPATH_D3D10:
5495         case RENDERPATH_D3D11:
5496         case RENDERPATH_SOFT:
5497         case RENDERPATH_GLES2:
5498                 break;
5499         case RENDERPATH_GL11:
5500         case RENDERPATH_GL13:
5501         case RENDERPATH_GLES1:
5502                 return;
5503         }
5504
5505         // set waterwidth and waterheight to the water resolution that will be
5506         // used (often less than the screen resolution for faster rendering)
5507         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5508
5509         // calculate desired texture sizes
5510         // can't use water if the card does not support the texture size
5511         if (!r_water.integer || r_showsurfaces.integer)
5512                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5513         else if (vid.support.arb_texture_non_power_of_two)
5514         {
5515                 texturewidth = waterwidth;
5516                 textureheight = waterheight;
5517                 camerawidth = waterwidth;
5518                 cameraheight = waterheight;
5519         }
5520         else
5521         {
5522                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5523                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5524                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5525                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5526         }
5527
5528         // allocate textures as needed
5529         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))
5530         {
5531                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5532                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5533                 {
5534                         if (p->texture_refraction)
5535                                 R_FreeTexture(p->texture_refraction);
5536                         p->texture_refraction = NULL;
5537                         if (p->fbo_refraction)
5538                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5539                         p->fbo_refraction = 0;
5540                         if (p->texture_reflection)
5541                                 R_FreeTexture(p->texture_reflection);
5542                         p->texture_reflection = NULL;
5543                         if (p->fbo_reflection)
5544                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5545                         p->fbo_reflection = 0;
5546                         if (p->texture_camera)
5547                                 R_FreeTexture(p->texture_camera);
5548                         p->texture_camera = NULL;
5549                         if (p->fbo_camera)
5550                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5551                         p->fbo_camera = 0;
5552                 }
5553                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5554                 r_fb.water.texturewidth = texturewidth;
5555                 r_fb.water.textureheight = textureheight;
5556                 r_fb.water.camerawidth = camerawidth;
5557                 r_fb.water.cameraheight = cameraheight;
5558         }
5559
5560         if (r_fb.water.texturewidth)
5561         {
5562                 int scaledwidth, scaledheight;
5563
5564                 r_fb.water.enabled = true;
5565
5566                 // water resolution is usually reduced
5567                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5568                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5569                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5570
5571                 // set up variables that will be used in shader setup
5572                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5573                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5574                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5575                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5576         }
5577
5578         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5579         r_fb.water.numwaterplanes = 0;
5580 }
5581
5582 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5583 {
5584         int planeindex, bestplaneindex, vertexindex;
5585         vec3_t mins, maxs, normal, center, v, n;
5586         vec_t planescore, bestplanescore;
5587         mplane_t plane;
5588         r_waterstate_waterplane_t *p;
5589         texture_t *t = R_GetCurrentTexture(surface->texture);
5590
5591         rsurface.texture = t;
5592         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5593         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5594         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5595                 return;
5596         // average the vertex normals, find the surface bounds (after deformvertexes)
5597         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5598         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5599         VectorCopy(n, normal);
5600         VectorCopy(v, mins);
5601         VectorCopy(v, maxs);
5602         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5603         {
5604                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5605                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5606                 VectorAdd(normal, n, normal);
5607                 mins[0] = min(mins[0], v[0]);
5608                 mins[1] = min(mins[1], v[1]);
5609                 mins[2] = min(mins[2], v[2]);
5610                 maxs[0] = max(maxs[0], v[0]);
5611                 maxs[1] = max(maxs[1], v[1]);
5612                 maxs[2] = max(maxs[2], v[2]);
5613         }
5614         VectorNormalize(normal);
5615         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5616
5617         VectorCopy(normal, plane.normal);
5618         VectorNormalize(plane.normal);
5619         plane.dist = DotProduct(center, plane.normal);
5620         PlaneClassify(&plane);
5621         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5622         {
5623                 // skip backfaces (except if nocullface is set)
5624 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5625 //                      return;
5626                 VectorNegate(plane.normal, plane.normal);
5627                 plane.dist *= -1;
5628                 PlaneClassify(&plane);
5629         }
5630
5631
5632         // find a matching plane if there is one
5633         bestplaneindex = -1;
5634         bestplanescore = 1048576.0f;
5635         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5636         {
5637                 if(p->camera_entity == t->camera_entity)
5638                 {
5639                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5640                         if (bestplaneindex < 0 || bestplanescore > planescore)
5641                         {
5642                                 bestplaneindex = planeindex;
5643                                 bestplanescore = planescore;
5644                         }
5645                 }
5646         }
5647         planeindex = bestplaneindex;
5648         p = r_fb.water.waterplanes + planeindex;
5649
5650         // if this surface does not fit any known plane rendered this frame, add one
5651         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5652         {
5653                 // store the new plane
5654                 planeindex = r_fb.water.numwaterplanes++;
5655                 p = r_fb.water.waterplanes + planeindex;
5656                 p->plane = plane;
5657                 // clear materialflags and pvs
5658                 p->materialflags = 0;
5659                 p->pvsvalid = false;
5660                 p->camera_entity = t->camera_entity;
5661                 VectorCopy(mins, p->mins);
5662                 VectorCopy(maxs, p->maxs);
5663         }
5664         else
5665         {
5666                 // merge mins/maxs when we're adding this surface to the plane
5667                 p->mins[0] = min(p->mins[0], mins[0]);
5668                 p->mins[1] = min(p->mins[1], mins[1]);
5669                 p->mins[2] = min(p->mins[2], mins[2]);
5670                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5671                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5672                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5673         }
5674         // merge this surface's materialflags into the waterplane
5675         p->materialflags |= t->currentmaterialflags;
5676         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5677         {
5678                 // merge this surface's PVS into the waterplane
5679                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5680                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5681                 {
5682                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5683                         p->pvsvalid = true;
5684                 }
5685         }
5686 }
5687
5688 extern cvar_t r_drawparticles;
5689 extern cvar_t r_drawdecals;
5690
5691 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5692 {
5693         int myscissor[4];
5694         r_refdef_view_t originalview;
5695         r_refdef_view_t myview;
5696         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;
5697         r_waterstate_waterplane_t *p;
5698         vec3_t visorigin;
5699         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5700         char vabuf[1024];
5701
5702         originalview = r_refdef.view;
5703
5704         // lowquality hack, temporarily shut down some cvars and restore afterwards
5705         qualityreduction = r_water_lowquality.integer;
5706         if (qualityreduction > 0)
5707         {
5708                 if (qualityreduction >= 1)
5709                 {
5710                         old_r_shadows = r_shadows.integer;
5711                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5712                         old_r_dlight = r_shadow_realtime_dlight.integer;
5713                         Cvar_SetValueQuick(&r_shadows, 0);
5714                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5715                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5716                 }
5717                 if (qualityreduction >= 2)
5718                 {
5719                         old_r_dynamic = r_dynamic.integer;
5720                         old_r_particles = r_drawparticles.integer;
5721                         old_r_decals = r_drawdecals.integer;
5722                         Cvar_SetValueQuick(&r_dynamic, 0);
5723                         Cvar_SetValueQuick(&r_drawparticles, 0);
5724                         Cvar_SetValueQuick(&r_drawdecals, 0);
5725                 }
5726         }
5727
5728         // make sure enough textures are allocated
5729         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5730         {
5731                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5732                 {
5733                         if (!p->texture_refraction)
5734                                 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);
5735                         if (!p->texture_refraction)
5736                                 goto error;
5737                         if (usewaterfbo)
5738                         {
5739                                 if (r_fb.water.depthtexture == NULL)
5740                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5741                                 if (p->fbo_refraction == 0)
5742                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5743                         }
5744                 }
5745                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5746                 {
5747                         if (!p->texture_camera)
5748                                 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);
5749                         if (!p->texture_camera)
5750                                 goto error;
5751                         if (usewaterfbo)
5752                         {
5753                                 if (r_fb.water.depthtexture == NULL)
5754                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5755                                 if (p->fbo_camera == 0)
5756                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5757                         }
5758                 }
5759
5760                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5761                 {
5762                         if (!p->texture_reflection)
5763                                 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);
5764                         if (!p->texture_reflection)
5765                                 goto error;
5766                         if (usewaterfbo)
5767                         {
5768                                 if (r_fb.water.depthtexture == NULL)
5769                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5770                                 if (p->fbo_reflection == 0)
5771                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5772                         }
5773                 }
5774         }
5775
5776         // render views
5777         r_refdef.view = originalview;
5778         r_refdef.view.showdebug = false;
5779         r_refdef.view.width = r_fb.water.waterwidth;
5780         r_refdef.view.height = r_fb.water.waterheight;
5781         r_refdef.view.useclipplane = true;
5782         myview = r_refdef.view;
5783         r_fb.water.renderingscene = true;
5784         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5785         {
5786                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5787                 {
5788                         r_refdef.view = myview;
5789                         if(r_water_scissormode.integer)
5790                         {
5791                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5792                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5793                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5794                         }
5795
5796                         // render reflected scene and copy into texture
5797                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5798                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5799                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5800                         r_refdef.view.clipplane = p->plane;
5801                         // reverse the cullface settings for this render
5802                         r_refdef.view.cullface_front = GL_FRONT;
5803                         r_refdef.view.cullface_back = GL_BACK;
5804                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5805                         {
5806                                 r_refdef.view.usecustompvs = true;
5807                                 if (p->pvsvalid)
5808                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5809                                 else
5810                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5811                         }
5812
5813                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5814                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5815                         R_ClearScreen(r_refdef.fogenabled);
5816                         if(r_water_scissormode.integer & 2)
5817                                 R_View_UpdateWithScissor(myscissor);
5818                         else
5819                                 R_View_Update();
5820                         if(r_water_scissormode.integer & 1)
5821                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5822                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5823
5824                         if (!p->fbo_reflection)
5825                                 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);
5826                         r_fb.water.hideplayer = false;
5827                 }
5828
5829                 // render the normal view scene and copy into texture
5830                 // (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)
5831                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5832                 {
5833                         r_refdef.view = myview;
5834                         if(r_water_scissormode.integer)
5835                         {
5836                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5837                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5838                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5839                         }
5840
5841                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5842
5843                         r_refdef.view.clipplane = p->plane;
5844                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5845                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5846
5847                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5848                         {
5849                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5850                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5851                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5852                                 R_RenderView_UpdateViewVectors();
5853                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5854                                 {
5855                                         r_refdef.view.usecustompvs = true;
5856                                         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);
5857                                 }
5858                         }
5859
5860                         PlaneClassify(&r_refdef.view.clipplane);
5861
5862                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5863                         R_ClearScreen(r_refdef.fogenabled);
5864                         if(r_water_scissormode.integer & 2)
5865                                 R_View_UpdateWithScissor(myscissor);
5866                         else
5867                                 R_View_Update();
5868                         if(r_water_scissormode.integer & 1)
5869                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5870                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5871
5872                         if (!p->fbo_refraction)
5873                                 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);
5874                         r_fb.water.hideplayer = false;
5875                 }
5876                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5877                 {
5878                         r_refdef.view = myview;
5879
5880                         r_refdef.view.clipplane = p->plane;
5881                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5882                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5883
5884                         r_refdef.view.width = r_fb.water.camerawidth;
5885                         r_refdef.view.height = r_fb.water.cameraheight;
5886                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5887                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5888                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5889                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5890
5891                         if(p->camera_entity)
5892                         {
5893                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5894                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5895                         }
5896
5897                         // note: all of the view is used for displaying... so
5898                         // there is no use in scissoring
5899
5900                         // reverse the cullface settings for this render
5901                         r_refdef.view.cullface_front = GL_FRONT;
5902                         r_refdef.view.cullface_back = GL_BACK;
5903                         // also reverse the view matrix
5904                         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
5905                         R_RenderView_UpdateViewVectors();
5906                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5907                         {
5908                                 r_refdef.view.usecustompvs = true;
5909                                 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);
5910                         }
5911                         
5912                         // camera needs no clipplane
5913                         r_refdef.view.useclipplane = false;
5914
5915                         PlaneClassify(&r_refdef.view.clipplane);
5916
5917                         r_fb.water.hideplayer = false;
5918
5919                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5920                         R_ClearScreen(r_refdef.fogenabled);
5921                         R_View_Update();
5922                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5923
5924                         if (!p->fbo_camera)
5925                                 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);
5926                         r_fb.water.hideplayer = false;
5927                 }
5928
5929         }
5930         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5931         r_fb.water.renderingscene = false;
5932         r_refdef.view = originalview;
5933         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5934         if (!r_fb.water.depthtexture)
5935                 R_ClearScreen(r_refdef.fogenabled);
5936         R_View_Update();
5937         goto finish;
5938 error:
5939         r_refdef.view = originalview;
5940         r_fb.water.renderingscene = false;
5941         Cvar_SetValueQuick(&r_water, 0);
5942         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5943 finish:
5944         // lowquality hack, restore cvars
5945         if (qualityreduction > 0)
5946         {
5947                 if (qualityreduction >= 1)
5948                 {
5949                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5950                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5951                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5952                 }
5953                 if (qualityreduction >= 2)
5954                 {
5955                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5956                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5957                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5958                 }
5959         }
5960 }
5961
5962 static void R_Bloom_StartFrame(void)
5963 {
5964         int i;
5965         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5966         int viewwidth, viewheight;
5967         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5968         textype_t textype = TEXTYPE_COLORBUFFER;
5969
5970         switch (vid.renderpath)
5971         {
5972         case RENDERPATH_GL20:
5973         case RENDERPATH_GLES2:
5974                 if (vid.support.ext_framebuffer_object)
5975                 {
5976                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5977                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5978                 }
5979                 break;
5980         case RENDERPATH_GL11:
5981         case RENDERPATH_GL13:
5982         case RENDERPATH_GLES1:
5983         case RENDERPATH_D3D9:
5984         case RENDERPATH_D3D10:
5985         case RENDERPATH_D3D11:
5986         case RENDERPATH_SOFT:
5987                 break;
5988         }
5989
5990         if (r_viewscale_fpsscaling.integer)
5991         {
5992                 double actualframetime;
5993                 double targetframetime;
5994                 double adjust;
5995                 actualframetime = r_refdef.lastdrawscreentime;
5996                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5997                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5998                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5999                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6000                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6001                 viewscalefpsadjusted += adjust;
6002                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6003         }
6004         else
6005                 viewscalefpsadjusted = 1.0f;
6006
6007         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6008
6009         switch(vid.renderpath)
6010         {
6011         case RENDERPATH_GL20:
6012         case RENDERPATH_D3D9:
6013         case RENDERPATH_D3D10:
6014         case RENDERPATH_D3D11:
6015         case RENDERPATH_SOFT:
6016         case RENDERPATH_GLES2:
6017                 break;
6018         case RENDERPATH_GL11:
6019         case RENDERPATH_GL13:
6020         case RENDERPATH_GLES1:
6021                 return;
6022         }
6023
6024         // set bloomwidth and bloomheight to the bloom resolution that will be
6025         // used (often less than the screen resolution for faster rendering)
6026         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6027         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6028         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6029         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6030         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6031
6032         // calculate desired texture sizes
6033         if (vid.support.arb_texture_non_power_of_two)
6034         {
6035                 screentexturewidth = vid.width;
6036                 screentextureheight = vid.height;
6037                 bloomtexturewidth = r_fb.bloomwidth;
6038                 bloomtextureheight = r_fb.bloomheight;
6039         }
6040         else
6041         {
6042                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6043                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6044                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6045                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6046         }
6047
6048         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))
6049         {
6050                 Cvar_SetValueQuick(&r_bloom, 0);
6051                 Cvar_SetValueQuick(&r_motionblur, 0);
6052                 Cvar_SetValueQuick(&r_damageblur, 0);
6053         }
6054
6055         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6056          && !r_bloom.integer
6057          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6058          && !useviewfbo
6059          && r_viewscale.value == 1.0f
6060          && !r_viewscale_fpsscaling.integer)
6061                 screentexturewidth = screentextureheight = 0;
6062         if (!r_bloom.integer)
6063                 bloomtexturewidth = bloomtextureheight = 0;
6064
6065         // allocate textures as needed
6066         if (r_fb.screentexturewidth != screentexturewidth
6067          || r_fb.screentextureheight != screentextureheight
6068          || r_fb.bloomtexturewidth != bloomtexturewidth
6069          || r_fb.bloomtextureheight != bloomtextureheight
6070          || r_fb.textype != textype
6071          || useviewfbo != (r_fb.fbo != 0))
6072         {
6073                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6074                 {
6075                         if (r_fb.bloomtexture[i])
6076                                 R_FreeTexture(r_fb.bloomtexture[i]);
6077                         r_fb.bloomtexture[i] = NULL;
6078
6079                         if (r_fb.bloomfbo[i])
6080                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6081                         r_fb.bloomfbo[i] = 0;
6082                 }
6083
6084                 if (r_fb.fbo)
6085                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6086                 r_fb.fbo = 0;
6087
6088                 if (r_fb.colortexture)
6089                         R_FreeTexture(r_fb.colortexture);
6090                 r_fb.colortexture = NULL;
6091
6092                 if (r_fb.depthtexture)
6093                         R_FreeTexture(r_fb.depthtexture);
6094                 r_fb.depthtexture = NULL;
6095
6096                 if (r_fb.ghosttexture)
6097                         R_FreeTexture(r_fb.ghosttexture);
6098                 r_fb.ghosttexture = NULL;
6099
6100                 r_fb.screentexturewidth = screentexturewidth;
6101                 r_fb.screentextureheight = screentextureheight;
6102                 r_fb.bloomtexturewidth = bloomtexturewidth;
6103                 r_fb.bloomtextureheight = bloomtextureheight;
6104                 r_fb.textype = textype;
6105
6106                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6107                 {
6108                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6109                                 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);
6110                         r_fb.ghosttexture_valid = false;
6111                         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);
6112                         if (useviewfbo)
6113                         {
6114                                 // FIXME: choose depth bits based on a cvar
6115                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6116                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6117                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6118 #ifndef USE_GLES2
6119                                 // render depth into one texture and color into the other
6120                                 if (qglDrawBuffer)
6121                                 {
6122                                         int status;
6123                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6124                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6125                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6126                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6127                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6128                                 }
6129 #endif
6130                         }
6131                 }
6132
6133                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6134                 {
6135                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6136                         {
6137                                 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);
6138                                 if (useviewfbo)
6139                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6140                         }
6141                 }
6142         }
6143
6144         // bloom texture is a different resolution
6145         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6146         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6147         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6148         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6149         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6150
6151         // set up a texcoord array for the full resolution screen image
6152         // (we have to keep this around to copy back during final render)
6153         r_fb.screentexcoord2f[0] = 0;
6154         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6155         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6156         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6157         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6158         r_fb.screentexcoord2f[5] = 0;
6159         r_fb.screentexcoord2f[6] = 0;
6160         r_fb.screentexcoord2f[7] = 0;
6161
6162         // set up a texcoord array for the reduced resolution bloom image
6163         // (which will be additive blended over the screen image)
6164         r_fb.bloomtexcoord2f[0] = 0;
6165         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6166         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6167         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6168         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6169         r_fb.bloomtexcoord2f[5] = 0;
6170         r_fb.bloomtexcoord2f[6] = 0;
6171         r_fb.bloomtexcoord2f[7] = 0;
6172
6173         switch(vid.renderpath)
6174         {
6175         case RENDERPATH_GL11:
6176         case RENDERPATH_GL13:
6177         case RENDERPATH_GL20:
6178         case RENDERPATH_SOFT:
6179         case RENDERPATH_GLES1:
6180         case RENDERPATH_GLES2:
6181                 break;
6182         case RENDERPATH_D3D9:
6183         case RENDERPATH_D3D10:
6184         case RENDERPATH_D3D11:
6185                 {
6186                         int i;
6187                         for (i = 0;i < 4;i++)
6188                         {
6189                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6190                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6191                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6192                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6193                         }
6194                 }
6195                 break;
6196         }
6197
6198         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);
6199
6200         if (r_fb.fbo)
6201                 r_refdef.view.clear = true;
6202 }
6203
6204 static void R_Bloom_MakeTexture(void)
6205 {
6206         int x, range, dir;
6207         float xoffset, yoffset, r, brighten;
6208         rtexture_t *intex;
6209         float colorscale = r_bloom_colorscale.value;
6210
6211         r_refdef.stats.bloom++;
6212
6213         if (!r_fb.fbo)
6214         {
6215                 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);
6216                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6217         }
6218
6219         // scale down screen texture to the bloom texture size
6220         CHECKGLERROR
6221         r_fb.bloomindex = 0;
6222         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6223         R_SetViewport(&r_fb.bloomviewport);
6224         GL_BlendFunc(GL_ONE, GL_ZERO);
6225         GL_Color(colorscale, colorscale, colorscale, 1);
6226         // 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...
6227         switch(vid.renderpath)
6228         {
6229         case RENDERPATH_GL11:
6230         case RENDERPATH_GL13:
6231         case RENDERPATH_GL20:
6232         case RENDERPATH_GLES1:
6233         case RENDERPATH_GLES2:
6234         case RENDERPATH_SOFT:
6235                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6236                 break;
6237         case RENDERPATH_D3D9:
6238         case RENDERPATH_D3D10:
6239         case RENDERPATH_D3D11:
6240                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6241                 break;
6242         }
6243         // TODO: do boxfilter scale-down in shader?
6244         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6245         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6246         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6247
6248         // we now have a properly scaled bloom image
6249         if (!r_fb.bloomfbo[r_fb.bloomindex])
6250         {
6251                 // copy it into the bloom texture
6252                 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);
6253                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6254         }
6255
6256         // multiply bloom image by itself as many times as desired
6257         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6258         {
6259                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6260                 r_fb.bloomindex ^= 1;
6261                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6262                 x *= 2;
6263                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6264                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6265                 GL_Color(r,r,r,1);
6266                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6267                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6268                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6269                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6270
6271                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6272                 {
6273                         // copy the darkened image to a texture
6274                         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);
6275                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6276                 }
6277         }
6278
6279         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6280         brighten = r_bloom_brighten.value;
6281         brighten = sqrt(brighten);
6282         if(range >= 1)
6283                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6284
6285         for (dir = 0;dir < 2;dir++)
6286         {
6287                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6288                 r_fb.bloomindex ^= 1;
6289                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6290                 // blend on at multiple vertical offsets to achieve a vertical blur
6291                 // TODO: do offset blends using GLSL
6292                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6293                 GL_BlendFunc(GL_ONE, GL_ZERO);
6294                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6295                 for (x = -range;x <= range;x++)
6296                 {
6297                         if (!dir){xoffset = 0;yoffset = x;}
6298                         else {xoffset = x;yoffset = 0;}
6299                         xoffset /= (float)r_fb.bloomtexturewidth;
6300                         yoffset /= (float)r_fb.bloomtextureheight;
6301                         // compute a texcoord array with the specified x and y offset
6302                         r_fb.offsettexcoord2f[0] = xoffset+0;
6303                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6304                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6305                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6306                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6307                         r_fb.offsettexcoord2f[5] = yoffset+0;
6308                         r_fb.offsettexcoord2f[6] = xoffset+0;
6309                         r_fb.offsettexcoord2f[7] = yoffset+0;
6310                         // this r value looks like a 'dot' particle, fading sharply to
6311                         // black at the edges
6312                         // (probably not realistic but looks good enough)
6313                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6314                         //r = brighten/(range*2+1);
6315                         r = brighten / (range * 2 + 1);
6316                         if(range >= 1)
6317                                 r *= (1 - x*x/(float)(range*range));
6318                         GL_Color(r, r, r, 1);
6319                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6320                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6321                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6322                         GL_BlendFunc(GL_ONE, GL_ONE);
6323                 }
6324
6325                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6326                 {
6327                         // copy the vertically or horizontally blurred bloom view to a texture
6328                         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);
6329                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6330                 }
6331         }
6332 }
6333
6334 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6335 {
6336         unsigned int permutation;
6337         float uservecs[4][4];
6338
6339         switch (vid.renderpath)
6340         {
6341         case RENDERPATH_GL20:
6342         case RENDERPATH_D3D9:
6343         case RENDERPATH_D3D10:
6344         case RENDERPATH_D3D11:
6345         case RENDERPATH_SOFT:
6346         case RENDERPATH_GLES2:
6347                 permutation =
6348                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6349                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6350                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6351                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6352                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6353
6354                 if (r_fb.colortexture)
6355                 {
6356                         if (!r_fb.fbo)
6357                         {
6358                                 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);
6359                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6360                         }
6361
6362                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6363                         {
6364                                 // declare variables
6365                                 float blur_factor, blur_mouseaccel, blur_velocity;
6366                                 static float blur_average; 
6367                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6368
6369                                 // set a goal for the factoring
6370                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6371                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6372                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6373                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6374                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6375                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6376
6377                                 // from the goal, pick an averaged value between goal and last value
6378                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6379                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6380
6381                                 // enforce minimum amount of blur 
6382                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6383
6384                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6385
6386                                 // calculate values into a standard alpha
6387                                 cl.motionbluralpha = 1 - exp(-
6388                                                 (
6389                                                  (r_motionblur.value * blur_factor / 80)
6390                                                  +
6391                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6392                                                 )
6393                                                 /
6394                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6395                                           );
6396
6397                                 // randomization for the blur value to combat persistent ghosting
6398                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6399                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6400
6401                                 // apply the blur
6402                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6403                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6404                                 {
6405                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6406                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6407                                         switch(vid.renderpath)
6408                                         {
6409                                         case RENDERPATH_GL11:
6410                                         case RENDERPATH_GL13:
6411                                         case RENDERPATH_GL20:
6412                                         case RENDERPATH_GLES1:
6413                                         case RENDERPATH_GLES2:
6414                                         case RENDERPATH_SOFT:
6415                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6416                                                 break;
6417                                         case RENDERPATH_D3D9:
6418                                         case RENDERPATH_D3D10:
6419                                         case RENDERPATH_D3D11:
6420                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6421                                                 break;
6422                                         }
6423                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6424                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6425                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6426                                 }
6427
6428                                 // updates old view angles for next pass
6429                                 VectorCopy(cl.viewangles, blur_oldangles);
6430
6431                                 // copy view into the ghost texture
6432                                 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);
6433                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6434                                 r_fb.ghosttexture_valid = true;
6435                         }
6436                 }
6437                 else
6438                 {
6439                         // no r_fb.colortexture means we're rendering to the real fb
6440                         // we may still have to do view tint...
6441                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6442                         {
6443                                 // apply a color tint to the whole view
6444                                 R_ResetViewRendering2D(0, NULL, NULL);
6445                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6446                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6447                                 R_SetupShader_Generic_NoTexture(false, true);
6448                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6449                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6450                         }
6451                         break; // no screen processing, no bloom, skip it
6452                 }
6453
6454                 if (r_fb.bloomtexture[0])
6455                 {
6456                         // make the bloom texture
6457                         R_Bloom_MakeTexture();
6458                 }
6459
6460 #if _MSC_VER >= 1400
6461 #define sscanf sscanf_s
6462 #endif
6463                 memset(uservecs, 0, sizeof(uservecs));
6464                 if (r_glsl_postprocess_uservec1_enable.integer)
6465                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6466                 if (r_glsl_postprocess_uservec2_enable.integer)
6467                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6468                 if (r_glsl_postprocess_uservec3_enable.integer)
6469                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6470                 if (r_glsl_postprocess_uservec4_enable.integer)
6471                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6472
6473                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6474                 GL_Color(1, 1, 1, 1);
6475                 GL_BlendFunc(GL_ONE, GL_ZERO);
6476
6477                 switch(vid.renderpath)
6478                 {
6479                 case RENDERPATH_GL20:
6480                 case RENDERPATH_GLES2:
6481                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6482                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6483                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6484                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6485                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6486                         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]);
6487                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6488                         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]);
6489                         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]);
6490                         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]);
6491                         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]);
6492                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6493                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6494                         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);
6495                         break;
6496                 case RENDERPATH_D3D9:
6497 #ifdef SUPPORTD3D
6498                         // 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...
6499                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6500                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6501                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6502                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6503                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6504                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6505                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6506                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6507                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6508                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6509                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6510                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6511                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6512                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6513 #endif
6514                         break;
6515                 case RENDERPATH_D3D10:
6516                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6517                         break;
6518                 case RENDERPATH_D3D11:
6519                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6520                         break;
6521                 case RENDERPATH_SOFT:
6522                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6523                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6524                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6525                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6526                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6527                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6528                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6529                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6530                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6531                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6532                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6533                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6534                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6535                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6536                         break;
6537                 default:
6538                         break;
6539                 }
6540                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6541                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6542                 break;
6543         case RENDERPATH_GL11:
6544         case RENDERPATH_GL13:
6545         case RENDERPATH_GLES1:
6546                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6547                 {
6548                         // apply a color tint to the whole view
6549                         R_ResetViewRendering2D(0, NULL, NULL);
6550                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6551                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6552                         R_SetupShader_Generic_NoTexture(false, true);
6553                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6554                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6555                 }
6556                 break;
6557         }
6558 }
6559
6560 matrix4x4_t r_waterscrollmatrix;
6561
6562 void R_UpdateFog(void)
6563 {
6564         // Nehahra fog
6565         if (gamemode == GAME_NEHAHRA)
6566         {
6567                 if (gl_fogenable.integer)
6568                 {
6569                         r_refdef.oldgl_fogenable = true;
6570                         r_refdef.fog_density = gl_fogdensity.value;
6571                         r_refdef.fog_red = gl_fogred.value;
6572                         r_refdef.fog_green = gl_foggreen.value;
6573                         r_refdef.fog_blue = gl_fogblue.value;
6574                         r_refdef.fog_alpha = 1;
6575                         r_refdef.fog_start = 0;
6576                         r_refdef.fog_end = gl_skyclip.value;
6577                         r_refdef.fog_height = 1<<30;
6578                         r_refdef.fog_fadedepth = 128;
6579                 }
6580                 else if (r_refdef.oldgl_fogenable)
6581                 {
6582                         r_refdef.oldgl_fogenable = false;
6583                         r_refdef.fog_density = 0;
6584                         r_refdef.fog_red = 0;
6585                         r_refdef.fog_green = 0;
6586                         r_refdef.fog_blue = 0;
6587                         r_refdef.fog_alpha = 0;
6588                         r_refdef.fog_start = 0;
6589                         r_refdef.fog_end = 0;
6590                         r_refdef.fog_height = 1<<30;
6591                         r_refdef.fog_fadedepth = 128;
6592                 }
6593         }
6594
6595         // fog parms
6596         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6597         r_refdef.fog_start = max(0, r_refdef.fog_start);
6598         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6599
6600         if (r_refdef.fog_density && r_drawfog.integer)
6601         {
6602                 r_refdef.fogenabled = true;
6603                 // this is the point where the fog reaches 0.9986 alpha, which we
6604                 // consider a good enough cutoff point for the texture
6605                 // (0.9986 * 256 == 255.6)
6606                 if (r_fog_exp2.integer)
6607                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6608                 else
6609                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6610                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6611                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6612                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6613                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6614                         R_BuildFogHeightTexture();
6615                 // fog color was already set
6616                 // update the fog texture
6617                 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)
6618                         R_BuildFogTexture();
6619                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6620                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6621         }
6622         else
6623                 r_refdef.fogenabled = false;
6624
6625         // fog color
6626         if (r_refdef.fog_density)
6627         {
6628                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6629                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6630                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6631
6632                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6633                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6634                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6635                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6636
6637                 {
6638                         vec3_t fogvec;
6639                         VectorCopy(r_refdef.fogcolor, fogvec);
6640                         //   color.rgb *= ContrastBoost * SceneBrightness;
6641                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6642                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6643                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6644                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6645                 }
6646         }
6647 }
6648
6649 void R_UpdateVariables(void)
6650 {
6651         R_Textures_Frame();
6652
6653         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6654
6655         r_refdef.farclip = r_farclip_base.value;
6656         if (r_refdef.scene.worldmodel)
6657                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6658         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6659
6660         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6661                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6662         r_refdef.polygonfactor = 0;
6663         r_refdef.polygonoffset = 0;
6664         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6665         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6666
6667         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6668         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6669         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6670         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6671         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6672         if (FAKELIGHT_ENABLED)
6673         {
6674                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6675         }
6676         if (r_showsurfaces.integer)
6677         {
6678                 r_refdef.scene.rtworld = false;
6679                 r_refdef.scene.rtworldshadows = false;
6680                 r_refdef.scene.rtdlight = false;
6681                 r_refdef.scene.rtdlightshadows = false;
6682                 r_refdef.lightmapintensity = 0;
6683         }
6684
6685         switch(vid.renderpath)
6686         {
6687         case RENDERPATH_GL20:
6688         case RENDERPATH_D3D9:
6689         case RENDERPATH_D3D10:
6690         case RENDERPATH_D3D11:
6691         case RENDERPATH_SOFT:
6692         case RENDERPATH_GLES2:
6693                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6694                 {
6695                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6696                         {
6697                                 // build GLSL gamma texture
6698 #define RAMPWIDTH 256
6699                                 unsigned short ramp[RAMPWIDTH * 3];
6700                                 unsigned char rampbgr[RAMPWIDTH][4];
6701                                 int i;
6702
6703                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6704
6705                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6706                                 for(i = 0; i < RAMPWIDTH; ++i)
6707                                 {
6708                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6709                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6710                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6711                                         rampbgr[i][3] = 0;
6712                                 }
6713                                 if (r_texture_gammaramps)
6714                                 {
6715                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6716                                 }
6717                                 else
6718                                 {
6719                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6720                                 }
6721                         }
6722                 }
6723                 else
6724                 {
6725                         // remove GLSL gamma texture
6726                 }
6727                 break;
6728         case RENDERPATH_GL11:
6729         case RENDERPATH_GL13:
6730         case RENDERPATH_GLES1:
6731                 break;
6732         }
6733 }
6734
6735 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6736 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6737 /*
6738 ================
6739 R_SelectScene
6740 ================
6741 */
6742 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6743         if( scenetype != r_currentscenetype ) {
6744                 // store the old scenetype
6745                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6746                 r_currentscenetype = scenetype;
6747                 // move in the new scene
6748                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6749         }
6750 }
6751
6752 /*
6753 ================
6754 R_GetScenePointer
6755 ================
6756 */
6757 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6758 {
6759         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6760         if( scenetype == r_currentscenetype ) {
6761                 return &r_refdef.scene;
6762         } else {
6763                 return &r_scenes_store[ scenetype ];
6764         }
6765 }
6766
6767 static int R_SortEntities_Compare(const void *ap, const void *bp)
6768 {
6769         const entity_render_t *a = *(const entity_render_t **)ap;
6770         const entity_render_t *b = *(const entity_render_t **)bp;
6771
6772         // 1. compare model
6773         if(a->model < b->model)
6774                 return -1;
6775         if(a->model > b->model)
6776                 return +1;
6777
6778         // 2. compare skin
6779         // TODO possibly calculate the REAL skinnum here first using
6780         // skinscenes?
6781         if(a->skinnum < b->skinnum)
6782                 return -1;
6783         if(a->skinnum > b->skinnum)
6784                 return +1;
6785
6786         // everything we compared is equal
6787         return 0;
6788 }
6789 static void R_SortEntities(void)
6790 {
6791         // below or equal 2 ents, sorting never gains anything
6792         if(r_refdef.scene.numentities <= 2)
6793                 return;
6794         // sort
6795         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6796 }
6797
6798 /*
6799 ================
6800 R_RenderView
6801 ================
6802 */
6803 int dpsoftrast_test;
6804 extern cvar_t r_shadow_bouncegrid;
6805 void R_RenderView(void)
6806 {
6807         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6808         int fbo;
6809         rtexture_t *depthtexture;
6810         rtexture_t *colortexture;
6811
6812         dpsoftrast_test = r_test.integer;
6813
6814         if (r_timereport_active)
6815                 R_TimeReport("start");
6816         r_textureframe++; // used only by R_GetCurrentTexture
6817         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6818
6819         if(R_CompileShader_CheckStaticParms())
6820                 R_GLSL_Restart_f();
6821
6822         if (!r_drawentities.integer)
6823                 r_refdef.scene.numentities = 0;
6824         else if (r_sortentities.integer)
6825                 R_SortEntities();
6826
6827         R_AnimCache_ClearCache();
6828         R_FrameData_NewFrame();
6829
6830         /* adjust for stereo display */
6831         if(R_Stereo_Active())
6832         {
6833                 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);
6834                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6835         }
6836
6837         if (r_refdef.view.isoverlay)
6838         {
6839                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6840                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6841                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6842                 R_TimeReport("depthclear");
6843
6844                 r_refdef.view.showdebug = false;
6845
6846                 r_fb.water.enabled = false;
6847                 r_fb.water.numwaterplanes = 0;
6848
6849                 R_RenderScene(0, NULL, NULL);
6850
6851                 r_refdef.view.matrix = originalmatrix;
6852
6853                 CHECKGLERROR
6854                 return;
6855         }
6856
6857         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6858         {
6859                 r_refdef.view.matrix = originalmatrix;
6860                 return;
6861         }
6862
6863         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6864
6865         R_RenderView_UpdateViewVectors();
6866
6867         R_Shadow_UpdateWorldLightSelection();
6868
6869         R_Bloom_StartFrame();
6870         R_Water_StartFrame();
6871
6872         // now we probably have an fbo to render into
6873         fbo = r_fb.fbo;
6874         depthtexture = r_fb.depthtexture;
6875         colortexture = r_fb.colortexture;
6876
6877         CHECKGLERROR
6878         if (r_timereport_active)
6879                 R_TimeReport("viewsetup");
6880
6881         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6882
6883         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6884         {
6885                 R_ClearScreen(r_refdef.fogenabled);
6886                 if (r_timereport_active)
6887                         R_TimeReport("viewclear");
6888         }
6889         r_refdef.view.clear = true;
6890
6891         r_refdef.view.showdebug = true;
6892
6893         R_View_Update();
6894         if (r_timereport_active)
6895                 R_TimeReport("visibility");
6896
6897         R_Shadow_UpdateBounceGridTexture();
6898         if (r_timereport_active && r_shadow_bouncegrid.integer)
6899                 R_TimeReport("bouncegrid");
6900
6901         r_fb.water.numwaterplanes = 0;
6902         if (r_fb.water.enabled)
6903                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6904
6905         R_RenderScene(fbo, depthtexture, colortexture);
6906         r_fb.water.numwaterplanes = 0;
6907
6908         R_BlendView(fbo, depthtexture, colortexture);
6909         if (r_timereport_active)
6910                 R_TimeReport("blendview");
6911
6912         GL_Scissor(0, 0, vid.width, vid.height);
6913         GL_ScissorTest(false);
6914
6915         r_refdef.view.matrix = originalmatrix;
6916
6917         CHECKGLERROR
6918 }
6919
6920 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6921 {
6922         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6923         {
6924                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6925                 if (r_timereport_active)
6926                         R_TimeReport("waterworld");
6927         }
6928
6929         // don't let sound skip if going slow
6930         if (r_refdef.scene.extraupdate)
6931                 S_ExtraUpdate ();
6932
6933         R_DrawModelsAddWaterPlanes();
6934         if (r_timereport_active)
6935                 R_TimeReport("watermodels");
6936
6937         if (r_fb.water.numwaterplanes)
6938         {
6939                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6940                 if (r_timereport_active)
6941                         R_TimeReport("waterscenes");
6942         }
6943 }
6944
6945 extern cvar_t cl_locs_show;
6946 static void R_DrawLocs(void);
6947 static void R_DrawEntityBBoxes(void);
6948 static void R_DrawModelDecals(void);
6949 extern cvar_t cl_decals_newsystem;
6950 extern qboolean r_shadow_usingdeferredprepass;
6951 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6952 {
6953         qboolean shadowmapping = false;
6954
6955         if (r_timereport_active)
6956                 R_TimeReport("beginscene");
6957
6958         r_refdef.stats.renders++;
6959
6960         R_UpdateFog();
6961
6962         // don't let sound skip if going slow
6963         if (r_refdef.scene.extraupdate)
6964                 S_ExtraUpdate ();
6965
6966         R_MeshQueue_BeginScene();
6967
6968         R_SkyStartFrame();
6969
6970         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);
6971
6972         if (r_timereport_active)
6973                 R_TimeReport("skystartframe");
6974
6975         if (cl.csqc_vidvars.drawworld)
6976         {
6977                 // don't let sound skip if going slow
6978                 if (r_refdef.scene.extraupdate)
6979                         S_ExtraUpdate ();
6980
6981                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6982                 {
6983                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6984                         if (r_timereport_active)
6985                                 R_TimeReport("worldsky");
6986                 }
6987
6988                 if (R_DrawBrushModelsSky() && r_timereport_active)
6989                         R_TimeReport("bmodelsky");
6990
6991                 if (skyrendermasked && skyrenderlater)
6992                 {
6993                         // we have to force off the water clipping plane while rendering sky
6994                         R_SetupView(false, fbo, depthtexture, colortexture);
6995                         R_Sky();
6996                         R_SetupView(true, fbo, depthtexture, colortexture);
6997                         if (r_timereport_active)
6998                                 R_TimeReport("sky");
6999                 }
7000         }
7001
7002         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7003         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7004                 R_Shadow_PrepareModelShadows();
7005         if (r_timereport_active)
7006                 R_TimeReport("preparelights");
7007
7008         if (R_Shadow_ShadowMappingEnabled())
7009                 shadowmapping = true;
7010
7011         if (r_shadow_usingdeferredprepass)
7012                 R_Shadow_DrawPrepass();
7013
7014         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7015         {
7016                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7017                 if (r_timereport_active)
7018                         R_TimeReport("worlddepth");
7019         }
7020         if (r_depthfirst.integer >= 2)
7021         {
7022                 R_DrawModelsDepth();
7023                 if (r_timereport_active)
7024                         R_TimeReport("modeldepth");
7025         }
7026
7027         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7028         {
7029                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7030                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7031                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7032                 // don't let sound skip if going slow
7033                 if (r_refdef.scene.extraupdate)
7034                         S_ExtraUpdate ();
7035         }
7036
7037         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7038         {
7039                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7040                 if (r_timereport_active)
7041                         R_TimeReport("world");
7042         }
7043
7044         // don't let sound skip if going slow
7045         if (r_refdef.scene.extraupdate)
7046                 S_ExtraUpdate ();
7047
7048         R_DrawModels();
7049         if (r_timereport_active)
7050                 R_TimeReport("models");
7051
7052         // don't let sound skip if going slow
7053         if (r_refdef.scene.extraupdate)
7054                 S_ExtraUpdate ();
7055
7056         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7057         {
7058                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7059                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7060                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7061                 // don't let sound skip if going slow
7062                 if (r_refdef.scene.extraupdate)
7063                         S_ExtraUpdate ();
7064         }
7065
7066         if (!r_shadow_usingdeferredprepass)
7067         {
7068                 R_Shadow_DrawLights();
7069                 if (r_timereport_active)
7070                         R_TimeReport("rtlights");
7071         }
7072
7073         // don't let sound skip if going slow
7074         if (r_refdef.scene.extraupdate)
7075                 S_ExtraUpdate ();
7076
7077         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7078         {
7079                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7080                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7081                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7082                 // don't let sound skip if going slow
7083                 if (r_refdef.scene.extraupdate)
7084                         S_ExtraUpdate ();
7085         }
7086
7087         if (cl.csqc_vidvars.drawworld)
7088         {
7089                 if (cl_decals_newsystem.integer)
7090                 {
7091                         R_DrawModelDecals();
7092                         if (r_timereport_active)
7093                                 R_TimeReport("modeldecals");
7094                 }
7095                 else
7096                 {
7097                         R_DrawDecals();
7098                         if (r_timereport_active)
7099                                 R_TimeReport("decals");
7100                 }
7101
7102                 R_DrawParticles();
7103                 if (r_timereport_active)
7104                         R_TimeReport("particles");
7105
7106                 R_DrawExplosions();
7107                 if (r_timereport_active)
7108                         R_TimeReport("explosions");
7109
7110                 R_DrawLightningBeams();
7111                 if (r_timereport_active)
7112                         R_TimeReport("lightning");
7113         }
7114
7115         if (cl.csqc_loaded)
7116                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7117
7118         if (r_refdef.view.showdebug)
7119         {
7120                 if (cl_locs_show.integer)
7121                 {
7122                         R_DrawLocs();
7123                         if (r_timereport_active)
7124                                 R_TimeReport("showlocs");
7125                 }
7126
7127                 if (r_drawportals.integer)
7128                 {
7129                         R_DrawPortals();
7130                         if (r_timereport_active)
7131                                 R_TimeReport("portals");
7132                 }
7133
7134                 if (r_showbboxes.value > 0)
7135                 {
7136                         R_DrawEntityBBoxes();
7137                         if (r_timereport_active)
7138                                 R_TimeReport("bboxes");
7139                 }
7140         }
7141
7142         if (r_transparent.integer)
7143         {
7144                 R_MeshQueue_RenderTransparent();
7145                 if (r_timereport_active)
7146                         R_TimeReport("drawtrans");
7147         }
7148
7149         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))
7150         {
7151                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7152                 if (r_timereport_active)
7153                         R_TimeReport("worlddebug");
7154                 R_DrawModelsDebug();
7155                 if (r_timereport_active)
7156                         R_TimeReport("modeldebug");
7157         }
7158
7159         if (cl.csqc_vidvars.drawworld)
7160         {
7161                 R_Shadow_DrawCoronas();
7162                 if (r_timereport_active)
7163                         R_TimeReport("coronas");
7164         }
7165
7166 #if 0
7167         {
7168                 GL_DepthTest(false);
7169                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7170                 GL_Color(1, 1, 1, 1);
7171                 qglBegin(GL_POLYGON);
7172                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7173                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7174                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7175                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7176                 qglEnd();
7177                 qglBegin(GL_POLYGON);
7178                 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]);
7179                 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]);
7180                 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]);
7181                 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]);
7182                 qglEnd();
7183                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7184         }
7185 #endif
7186
7187         // don't let sound skip if going slow
7188         if (r_refdef.scene.extraupdate)
7189                 S_ExtraUpdate ();
7190 }
7191
7192 static const unsigned short bboxelements[36] =
7193 {
7194         5, 1, 3, 5, 3, 7,
7195         6, 2, 0, 6, 0, 4,
7196         7, 3, 2, 7, 2, 6,
7197         4, 0, 1, 4, 1, 5,
7198         4, 5, 7, 4, 7, 6,
7199         1, 0, 2, 1, 2, 3,
7200 };
7201
7202 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7203 {
7204         int i;
7205         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7206
7207         RSurf_ActiveWorldEntity();
7208
7209         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7210         GL_DepthMask(false);
7211         GL_DepthRange(0, 1);
7212         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7213 //      R_Mesh_ResetTextureState();
7214
7215         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7216         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7217         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7218         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7219         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7220         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7221         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7222         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7223         R_FillColors(color4f, 8, cr, cg, cb, ca);
7224         if (r_refdef.fogenabled)
7225         {
7226                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7227                 {
7228                         f1 = RSurf_FogVertex(v);
7229                         f2 = 1 - f1;
7230                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7231                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7232                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7233                 }
7234         }
7235         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7236         R_Mesh_ResetTextureState();
7237         R_SetupShader_Generic_NoTexture(false, false);
7238         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7239 }
7240
7241 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7242 {
7243         prvm_prog_t *prog = SVVM_prog;
7244         int i;
7245         float color[4];
7246         prvm_edict_t *edict;
7247
7248         // this function draws bounding boxes of server entities
7249         if (!sv.active)
7250                 return;
7251
7252         GL_CullFace(GL_NONE);
7253         R_SetupShader_Generic_NoTexture(false, false);
7254
7255         for (i = 0;i < numsurfaces;i++)
7256         {
7257                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7258                 switch ((int)PRVM_serveredictfloat(edict, solid))
7259                 {
7260                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7261                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7262                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7263                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7264                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7265                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7266                 }
7267                 color[3] *= r_showbboxes.value;
7268                 color[3] = bound(0, color[3], 1);
7269                 GL_DepthTest(!r_showdisabledepthtest.integer);
7270                 GL_CullFace(r_refdef.view.cullface_front);
7271                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7272         }
7273 }
7274
7275 static void R_DrawEntityBBoxes(void)
7276 {
7277         int i;
7278         prvm_edict_t *edict;
7279         vec3_t center;
7280         prvm_prog_t *prog = SVVM_prog;
7281
7282         // this function draws bounding boxes of server entities
7283         if (!sv.active)
7284                 return;
7285
7286         for (i = 0;i < prog->num_edicts;i++)
7287         {
7288                 edict = PRVM_EDICT_NUM(i);
7289                 if (edict->priv.server->free)
7290                         continue;
7291                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7292                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7293                         continue;
7294                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7295                         continue;
7296                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7297                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7298         }
7299 }
7300
7301 static const int nomodelelement3i[24] =
7302 {
7303         5, 2, 0,
7304         5, 1, 2,
7305         5, 0, 3,
7306         5, 3, 1,
7307         0, 2, 4,
7308         2, 1, 4,
7309         3, 0, 4,
7310         1, 3, 4
7311 };
7312
7313 static const unsigned short nomodelelement3s[24] =
7314 {
7315         5, 2, 0,
7316         5, 1, 2,
7317         5, 0, 3,
7318         5, 3, 1,
7319         0, 2, 4,
7320         2, 1, 4,
7321         3, 0, 4,
7322         1, 3, 4
7323 };
7324
7325 static const float nomodelvertex3f[6*3] =
7326 {
7327         -16,   0,   0,
7328          16,   0,   0,
7329           0, -16,   0,
7330           0,  16,   0,
7331           0,   0, -16,
7332           0,   0,  16
7333 };
7334
7335 static const float nomodelcolor4f[6*4] =
7336 {
7337         0.0f, 0.0f, 0.5f, 1.0f,
7338         0.0f, 0.0f, 0.5f, 1.0f,
7339         0.0f, 0.5f, 0.0f, 1.0f,
7340         0.0f, 0.5f, 0.0f, 1.0f,
7341         0.5f, 0.0f, 0.0f, 1.0f,
7342         0.5f, 0.0f, 0.0f, 1.0f
7343 };
7344
7345 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7346 {
7347         int i;
7348         float f1, f2, *c;
7349         float color4f[6*4];
7350
7351         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);
7352
7353         // this is only called once per entity so numsurfaces is always 1, and
7354         // surfacelist is always {0}, so this code does not handle batches
7355
7356         if (rsurface.ent_flags & RENDER_ADDITIVE)
7357         {
7358                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7359                 GL_DepthMask(false);
7360         }
7361         else if (rsurface.colormod[3] < 1)
7362         {
7363                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7364                 GL_DepthMask(false);
7365         }
7366         else
7367         {
7368                 GL_BlendFunc(GL_ONE, GL_ZERO);
7369                 GL_DepthMask(true);
7370         }
7371         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7372         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7373         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7374         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7375         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7376         for (i = 0, c = color4f;i < 6;i++, c += 4)
7377         {
7378                 c[0] *= rsurface.colormod[0];
7379                 c[1] *= rsurface.colormod[1];
7380                 c[2] *= rsurface.colormod[2];
7381                 c[3] *= rsurface.colormod[3];
7382         }
7383         if (r_refdef.fogenabled)
7384         {
7385                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7386                 {
7387                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7388                         f2 = 1 - f1;
7389                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7390                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7391                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7392                 }
7393         }
7394 //      R_Mesh_ResetTextureState();
7395         R_SetupShader_Generic_NoTexture(false, false);
7396         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7397         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7398 }
7399
7400 void R_DrawNoModel(entity_render_t *ent)
7401 {
7402         vec3_t org;
7403         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7404         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7405                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7406         else
7407                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7408 }
7409
7410 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7411 {
7412         vec3_t right1, right2, diff, normal;
7413
7414         VectorSubtract (org2, org1, normal);
7415
7416         // calculate 'right' vector for start
7417         VectorSubtract (r_refdef.view.origin, org1, diff);
7418         CrossProduct (normal, diff, right1);
7419         VectorNormalize (right1);
7420
7421         // calculate 'right' vector for end
7422         VectorSubtract (r_refdef.view.origin, org2, diff);
7423         CrossProduct (normal, diff, right2);
7424         VectorNormalize (right2);
7425
7426         vert[ 0] = org1[0] + width * right1[0];
7427         vert[ 1] = org1[1] + width * right1[1];
7428         vert[ 2] = org1[2] + width * right1[2];
7429         vert[ 3] = org1[0] - width * right1[0];
7430         vert[ 4] = org1[1] - width * right1[1];
7431         vert[ 5] = org1[2] - width * right1[2];
7432         vert[ 6] = org2[0] - width * right2[0];
7433         vert[ 7] = org2[1] - width * right2[1];
7434         vert[ 8] = org2[2] - width * right2[2];
7435         vert[ 9] = org2[0] + width * right2[0];
7436         vert[10] = org2[1] + width * right2[1];
7437         vert[11] = org2[2] + width * right2[2];
7438 }
7439
7440 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)
7441 {
7442         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7443         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7444         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7445         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7446         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7447         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7448         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7449         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7450         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7451         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7452         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7453         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7454 }
7455
7456 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7457 {
7458         int i;
7459         float *vertex3f;
7460         float v[3];
7461         VectorSet(v, x, y, z);
7462         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7463                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7464                         break;
7465         if (i == mesh->numvertices)
7466         {
7467                 if (mesh->numvertices < mesh->maxvertices)
7468                 {
7469                         VectorCopy(v, vertex3f);
7470                         mesh->numvertices++;
7471                 }
7472                 return mesh->numvertices;
7473         }
7474         else
7475                 return i;
7476 }
7477
7478 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7479 {
7480         int i;
7481         int *e, element[3];
7482         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7483         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7484         e = mesh->element3i + mesh->numtriangles * 3;
7485         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7486         {
7487                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7488                 if (mesh->numtriangles < mesh->maxtriangles)
7489                 {
7490                         *e++ = element[0];
7491                         *e++ = element[1];
7492                         *e++ = element[2];
7493                         mesh->numtriangles++;
7494                 }
7495                 element[1] = element[2];
7496         }
7497 }
7498
7499 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7500 {
7501         int i;
7502         int *e, element[3];
7503         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7504         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7505         e = mesh->element3i + mesh->numtriangles * 3;
7506         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7507         {
7508                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7509                 if (mesh->numtriangles < mesh->maxtriangles)
7510                 {
7511                         *e++ = element[0];
7512                         *e++ = element[1];
7513                         *e++ = element[2];
7514                         mesh->numtriangles++;
7515                 }
7516                 element[1] = element[2];
7517         }
7518 }
7519
7520 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7521 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7522 {
7523         int planenum, planenum2;
7524         int w;
7525         int tempnumpoints;
7526         mplane_t *plane, *plane2;
7527         double maxdist;
7528         double temppoints[2][256*3];
7529         // figure out how large a bounding box we need to properly compute this brush
7530         maxdist = 0;
7531         for (w = 0;w < numplanes;w++)
7532                 maxdist = max(maxdist, fabs(planes[w].dist));
7533         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7534         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7535         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7536         {
7537                 w = 0;
7538                 tempnumpoints = 4;
7539                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7540                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7541                 {
7542                         if (planenum2 == planenum)
7543                                 continue;
7544                         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);
7545                         w = !w;
7546                 }
7547                 if (tempnumpoints < 3)
7548                         continue;
7549                 // generate elements forming a triangle fan for this polygon
7550                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7551         }
7552 }
7553
7554 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)
7555 {
7556         texturelayer_t *layer;
7557         layer = t->currentlayers + t->currentnumlayers++;
7558         layer->type = type;
7559         layer->depthmask = depthmask;
7560         layer->blendfunc1 = blendfunc1;
7561         layer->blendfunc2 = blendfunc2;
7562         layer->texture = texture;
7563         layer->texmatrix = *matrix;
7564         layer->color[0] = r;
7565         layer->color[1] = g;
7566         layer->color[2] = b;
7567         layer->color[3] = a;
7568 }
7569
7570 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7571 {
7572         if(parms[0] == 0 && parms[1] == 0)
7573                 return false;
7574         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7575                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7576                         return false;
7577         return true;
7578 }
7579
7580 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7581 {
7582         double index, f;
7583         index = parms[2] + rsurface.shadertime * parms[3];
7584         index -= floor(index);
7585         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7586         {
7587         default:
7588         case Q3WAVEFUNC_NONE:
7589         case Q3WAVEFUNC_NOISE:
7590         case Q3WAVEFUNC_COUNT:
7591                 f = 0;
7592                 break;
7593         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7594         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7595         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7596         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7597         case Q3WAVEFUNC_TRIANGLE:
7598                 index *= 4;
7599                 f = index - floor(index);
7600                 if (index < 1)
7601                 {
7602                         // f = f;
7603                 }
7604                 else if (index < 2)
7605                         f = 1 - f;
7606                 else if (index < 3)
7607                         f = -f;
7608                 else
7609                         f = -(1 - f);
7610                 break;
7611         }
7612         f = parms[0] + parms[1] * f;
7613         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7614                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7615         return (float) f;
7616 }
7617
7618 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7619 {
7620         int w, h, idx;
7621         double f;
7622         double offsetd[2];
7623         float tcmat[12];
7624         matrix4x4_t matrix, temp;
7625         switch(tcmod->tcmod)
7626         {
7627                 case Q3TCMOD_COUNT:
7628                 case Q3TCMOD_NONE:
7629                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7630                                 matrix = r_waterscrollmatrix;
7631                         else
7632                                 matrix = identitymatrix;
7633                         break;
7634                 case Q3TCMOD_ENTITYTRANSLATE:
7635                         // this is used in Q3 to allow the gamecode to control texcoord
7636                         // scrolling on the entity, which is not supported in darkplaces yet.
7637                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7638                         break;
7639                 case Q3TCMOD_ROTATE:
7640                         f = tcmod->parms[0] * rsurface.shadertime;
7641                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7642                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7643                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7644                         break;
7645                 case Q3TCMOD_SCALE:
7646                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7647                         break;
7648                 case Q3TCMOD_SCROLL:
7649                         // extra care is needed because of precision breakdown with large values of time
7650                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7651                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7652                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7653                         break;
7654                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7655                         w = (int) tcmod->parms[0];
7656                         h = (int) tcmod->parms[1];
7657                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7658                         f = f - floor(f);
7659                         idx = (int) floor(f * w * h);
7660                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7661                         break;
7662                 case Q3TCMOD_STRETCH:
7663                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7664                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7665                         break;
7666                 case Q3TCMOD_TRANSFORM:
7667                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7668                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7669                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7670                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7671                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7672                         break;
7673                 case Q3TCMOD_TURBULENT:
7674                         // this is handled in the RSurf_PrepareVertices function
7675                         matrix = identitymatrix;
7676                         break;
7677         }
7678         temp = *texmatrix;
7679         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7680 }
7681
7682 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7683 {
7684         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7685         char name[MAX_QPATH];
7686         skinframe_t *skinframe;
7687         unsigned char pixels[296*194];
7688         strlcpy(cache->name, skinname, sizeof(cache->name));
7689         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7690         if (developer_loading.integer)
7691                 Con_Printf("loading %s\n", name);
7692         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7693         if (!skinframe || !skinframe->base)
7694         {
7695                 unsigned char *f;
7696                 fs_offset_t filesize;
7697                 skinframe = NULL;
7698                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7699                 if (f)
7700                 {
7701                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7702                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7703                         Mem_Free(f);
7704                 }
7705         }
7706         cache->skinframe = skinframe;
7707 }
7708
7709 texture_t *R_GetCurrentTexture(texture_t *t)
7710 {
7711         int i;
7712         const entity_render_t *ent = rsurface.entity;
7713         dp_model_t *model = ent->model;
7714         q3shaderinfo_layer_tcmod_t *tcmod;
7715
7716         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7717                 return t->currentframe;
7718         t->update_lastrenderframe = r_textureframe;
7719         t->update_lastrenderentity = (void *)ent;
7720
7721         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7722                 t->camera_entity = ent->entitynumber;
7723         else
7724                 t->camera_entity = 0;
7725
7726         // switch to an alternate material if this is a q1bsp animated material
7727         {
7728                 texture_t *texture = t;
7729                 int s = rsurface.ent_skinnum;
7730                 if ((unsigned int)s >= (unsigned int)model->numskins)
7731                         s = 0;
7732                 if (model->skinscenes)
7733                 {
7734                         if (model->skinscenes[s].framecount > 1)
7735                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7736                         else
7737                                 s = model->skinscenes[s].firstframe;
7738                 }
7739                 if (s > 0)
7740                         t = t + s * model->num_surfaces;
7741                 if (t->animated)
7742                 {
7743                         // use an alternate animation if the entity's frame is not 0,
7744                         // and only if the texture has an alternate animation
7745                         if (rsurface.ent_alttextures && t->anim_total[1])
7746                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7747                         else
7748                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7749                 }
7750                 texture->currentframe = t;
7751         }
7752
7753         // update currentskinframe to be a qw skin or animation frame
7754         if (rsurface.ent_qwskin >= 0)
7755         {
7756                 i = rsurface.ent_qwskin;
7757                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7758                 {
7759                         r_qwskincache_size = cl.maxclients;
7760                         if (r_qwskincache)
7761                                 Mem_Free(r_qwskincache);
7762                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7763                 }
7764                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7765                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7766                 t->currentskinframe = r_qwskincache[i].skinframe;
7767                 if (t->currentskinframe == NULL)
7768                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7769         }
7770         else if (t->numskinframes >= 2)
7771                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7772         if (t->backgroundnumskinframes >= 2)
7773                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7774
7775         t->currentmaterialflags = t->basematerialflags;
7776         t->currentalpha = rsurface.colormod[3];
7777         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7778                 t->currentalpha *= r_wateralpha.value;
7779         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7780                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7781         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7782                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7783         if (!(rsurface.ent_flags & RENDER_LIGHT))
7784                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7785         else if (FAKELIGHT_ENABLED)
7786         {
7787                 // no modellight if using fakelight for the map
7788         }
7789         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7790         {
7791                 // pick a model lighting mode
7792                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7793                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7794                 else
7795                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7796         }
7797         if (rsurface.ent_flags & RENDER_ADDITIVE)
7798                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7799         else if (t->currentalpha < 1)
7800                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7801         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7802         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7803                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7804         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7805                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7806         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7807                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7808         if (t->backgroundnumskinframes)
7809                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7810         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7811         {
7812                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7813                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7814         }
7815         else
7816                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7817         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7818         {
7819                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7820                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7821         }
7822         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7823                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7824
7825         // there is no tcmod
7826         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7827         {
7828                 t->currenttexmatrix = r_waterscrollmatrix;
7829                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7830         }
7831         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7832         {
7833                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7834                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7835         }
7836
7837         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7838                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7839         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7840                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7841
7842         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7843         if (t->currentskinframe->qpixels)
7844                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7845         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7846         if (!t->basetexture)
7847                 t->basetexture = r_texture_notexture;
7848         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7849         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7850         t->nmaptexture = t->currentskinframe->nmap;
7851         if (!t->nmaptexture)
7852                 t->nmaptexture = r_texture_blanknormalmap;
7853         t->glosstexture = r_texture_black;
7854         t->glowtexture = t->currentskinframe->glow;
7855         t->fogtexture = t->currentskinframe->fog;
7856         t->reflectmasktexture = t->currentskinframe->reflect;
7857         if (t->backgroundnumskinframes)
7858         {
7859                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7860                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7861                 t->backgroundglosstexture = r_texture_black;
7862                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7863                 if (!t->backgroundnmaptexture)
7864                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7865         }
7866         else
7867         {
7868                 t->backgroundbasetexture = r_texture_white;
7869                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7870                 t->backgroundglosstexture = r_texture_black;
7871                 t->backgroundglowtexture = NULL;
7872         }
7873         t->specularpower = r_shadow_glossexponent.value;
7874         // TODO: store reference values for these in the texture?
7875         t->specularscale = 0;
7876         if (r_shadow_gloss.integer > 0)
7877         {
7878                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7879                 {
7880                         if (r_shadow_glossintensity.value > 0)
7881                         {
7882                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7883                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7884                                 t->specularscale = r_shadow_glossintensity.value;
7885                         }
7886                 }
7887                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7888                 {
7889                         t->glosstexture = r_texture_white;
7890                         t->backgroundglosstexture = r_texture_white;
7891                         t->specularscale = r_shadow_gloss2intensity.value;
7892                         t->specularpower = r_shadow_gloss2exponent.value;
7893                 }
7894         }
7895         t->specularscale *= t->specularscalemod;
7896         t->specularpower *= t->specularpowermod;
7897         t->rtlightambient = 0;
7898
7899         // lightmaps mode looks bad with dlights using actual texturing, so turn
7900         // off the colormap and glossmap, but leave the normalmap on as it still
7901         // accurately represents the shading involved
7902         if (gl_lightmaps.integer)
7903         {
7904                 t->basetexture = r_texture_grey128;
7905                 t->pantstexture = r_texture_black;
7906                 t->shirttexture = r_texture_black;
7907                 t->nmaptexture = r_texture_blanknormalmap;
7908                 t->glosstexture = r_texture_black;
7909                 t->glowtexture = NULL;
7910                 t->fogtexture = NULL;
7911                 t->reflectmasktexture = NULL;
7912                 t->backgroundbasetexture = NULL;
7913                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7914                 t->backgroundglosstexture = r_texture_black;
7915                 t->backgroundglowtexture = NULL;
7916                 t->specularscale = 0;
7917                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7918         }
7919
7920         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7921         VectorClear(t->dlightcolor);
7922         t->currentnumlayers = 0;
7923         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7924         {
7925                 int blendfunc1, blendfunc2;
7926                 qboolean depthmask;
7927                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7928                 {
7929                         blendfunc1 = GL_SRC_ALPHA;
7930                         blendfunc2 = GL_ONE;
7931                 }
7932                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7933                 {
7934                         blendfunc1 = GL_SRC_ALPHA;
7935                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7936                 }
7937                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7938                 {
7939                         blendfunc1 = t->customblendfunc[0];
7940                         blendfunc2 = t->customblendfunc[1];
7941                 }
7942                 else
7943                 {
7944                         blendfunc1 = GL_ONE;
7945                         blendfunc2 = GL_ZERO;
7946                 }
7947                 // don't colormod evilblend textures
7948                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7949                         VectorSet(t->lightmapcolor, 1, 1, 1);
7950                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7951                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7952                 {
7953                         // fullbright is not affected by r_refdef.lightmapintensity
7954                         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]);
7955                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7956                                 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]);
7957                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7958                                 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]);
7959                 }
7960                 else
7961                 {
7962                         vec3_t ambientcolor;
7963                         float colorscale;
7964                         // set the color tint used for lights affecting this surface
7965                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7966                         colorscale = 2;
7967                         // q3bsp has no lightmap updates, so the lightstylevalue that
7968                         // would normally be baked into the lightmap must be
7969                         // applied to the color
7970                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7971                         if (model->type == mod_brushq3)
7972                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7973                         colorscale *= r_refdef.lightmapintensity;
7974                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7975                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7976                         // basic lit geometry
7977                         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]);
7978                         // add pants/shirt if needed
7979                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7980                                 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]);
7981                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7982                                 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]);
7983                         // now add ambient passes if needed
7984                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7985                         {
7986                                 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]);
7987                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7988                                         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]);
7989                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7990                                         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]);
7991                         }
7992                 }
7993                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7994                         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]);
7995                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7996                 {
7997                         // if this is opaque use alpha blend which will darken the earlier
7998                         // passes cheaply.
7999                         //
8000                         // if this is an alpha blended material, all the earlier passes
8001                         // were darkened by fog already, so we only need to add the fog
8002                         // color ontop through the fog mask texture
8003                         //
8004                         // if this is an additive blended material, all the earlier passes
8005                         // were darkened by fog already, and we should not add fog color
8006                         // (because the background was not darkened, there is no fog color
8007                         // that was lost behind it).
8008                         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]);
8009                 }
8010         }
8011
8012         return t->currentframe;
8013 }
8014
8015 rsurfacestate_t rsurface;
8016
8017 void RSurf_ActiveWorldEntity(void)
8018 {
8019         dp_model_t *model = r_refdef.scene.worldmodel;
8020         //if (rsurface.entity == r_refdef.scene.worldentity)
8021         //      return;
8022         rsurface.entity = r_refdef.scene.worldentity;
8023         rsurface.skeleton = NULL;
8024         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8025         rsurface.ent_skinnum = 0;
8026         rsurface.ent_qwskin = -1;
8027         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8028         rsurface.shadertime = r_refdef.scene.time;
8029         rsurface.matrix = identitymatrix;
8030         rsurface.inversematrix = identitymatrix;
8031         rsurface.matrixscale = 1;
8032         rsurface.inversematrixscale = 1;
8033         R_EntityMatrix(&identitymatrix);
8034         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8035         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8036         rsurface.fograngerecip = r_refdef.fograngerecip;
8037         rsurface.fogheightfade = r_refdef.fogheightfade;
8038         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8039         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8040         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8041         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8042         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8043         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8044         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8045         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8046         rsurface.colormod[3] = 1;
8047         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);
8048         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8049         rsurface.frameblend[0].lerp = 1;
8050         rsurface.ent_alttextures = false;
8051         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8052         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8053         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8054         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8055         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8056         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8057         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8058         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8059         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8060         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8061         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8062         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8063         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8064         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8065         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8066         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8067         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8068         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8069         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8070         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8071         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8072         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8073         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8074         rsurface.modelelement3i = model->surfmesh.data_element3i;
8075         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8076         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8077         rsurface.modelelement3s = model->surfmesh.data_element3s;
8078         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8079         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8080         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8081         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8082         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8083         rsurface.modelsurfaces = model->data_surfaces;
8084         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8085         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8086         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8087         rsurface.modelgeneratedvertex = false;
8088         rsurface.batchgeneratedvertex = false;
8089         rsurface.batchfirstvertex = 0;
8090         rsurface.batchnumvertices = 0;
8091         rsurface.batchfirsttriangle = 0;
8092         rsurface.batchnumtriangles = 0;
8093         rsurface.batchvertex3f  = NULL;
8094         rsurface.batchvertex3f_vertexbuffer = NULL;
8095         rsurface.batchvertex3f_bufferoffset = 0;
8096         rsurface.batchsvector3f = NULL;
8097         rsurface.batchsvector3f_vertexbuffer = NULL;
8098         rsurface.batchsvector3f_bufferoffset = 0;
8099         rsurface.batchtvector3f = NULL;
8100         rsurface.batchtvector3f_vertexbuffer = NULL;
8101         rsurface.batchtvector3f_bufferoffset = 0;
8102         rsurface.batchnormal3f  = NULL;
8103         rsurface.batchnormal3f_vertexbuffer = NULL;
8104         rsurface.batchnormal3f_bufferoffset = 0;
8105         rsurface.batchlightmapcolor4f = NULL;
8106         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8107         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8108         rsurface.batchtexcoordtexture2f = NULL;
8109         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8110         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8111         rsurface.batchtexcoordlightmap2f = NULL;
8112         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8113         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8114         rsurface.batchvertexmesh = NULL;
8115         rsurface.batchvertexmeshbuffer = NULL;
8116         rsurface.batchvertex3fbuffer = NULL;
8117         rsurface.batchelement3i = NULL;
8118         rsurface.batchelement3i_indexbuffer = NULL;
8119         rsurface.batchelement3i_bufferoffset = 0;
8120         rsurface.batchelement3s = NULL;
8121         rsurface.batchelement3s_indexbuffer = NULL;
8122         rsurface.batchelement3s_bufferoffset = 0;
8123         rsurface.passcolor4f = NULL;
8124         rsurface.passcolor4f_vertexbuffer = NULL;
8125         rsurface.passcolor4f_bufferoffset = 0;
8126 }
8127
8128 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8129 {
8130         dp_model_t *model = ent->model;
8131         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8132         //      return;
8133         rsurface.entity = (entity_render_t *)ent;
8134         rsurface.skeleton = ent->skeleton;
8135         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8136         rsurface.ent_skinnum = ent->skinnum;
8137         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;
8138         rsurface.ent_flags = ent->flags;
8139         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8140         rsurface.matrix = ent->matrix;
8141         rsurface.inversematrix = ent->inversematrix;
8142         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8143         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8144         R_EntityMatrix(&rsurface.matrix);
8145         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8146         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8147         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8148         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8149         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8150         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8151         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8152         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8153         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8154         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8155         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8156         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8157         rsurface.colormod[3] = ent->alpha;
8158         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8159         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8160         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8161         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8162         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8163         if (ent->model->brush.submodel && !prepass)
8164         {
8165                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8166                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8167         }
8168         if (model->surfmesh.isanimated && model->AnimateVertices)
8169         {
8170                 if (ent->animcache_vertex3f)
8171                 {
8172                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8173                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8174                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8175                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8176                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8177                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8178                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8179                 }
8180                 else if (wanttangents)
8181                 {
8182                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8183                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8185                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8186                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8187                         rsurface.modelvertexmesh = NULL;
8188                         rsurface.modelvertexmeshbuffer = NULL;
8189                         rsurface.modelvertex3fbuffer = NULL;
8190                 }
8191                 else if (wantnormals)
8192                 {
8193                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8194                         rsurface.modelsvector3f = NULL;
8195                         rsurface.modeltvector3f = NULL;
8196                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8197                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8198                         rsurface.modelvertexmesh = NULL;
8199                         rsurface.modelvertexmeshbuffer = NULL;
8200                         rsurface.modelvertex3fbuffer = NULL;
8201                 }
8202                 else
8203                 {
8204                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8205                         rsurface.modelsvector3f = NULL;
8206                         rsurface.modeltvector3f = NULL;
8207                         rsurface.modelnormal3f = NULL;
8208                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8209                         rsurface.modelvertexmesh = NULL;
8210                         rsurface.modelvertexmeshbuffer = NULL;
8211                         rsurface.modelvertex3fbuffer = NULL;
8212                 }
8213                 rsurface.modelvertex3f_vertexbuffer = 0;
8214                 rsurface.modelvertex3f_bufferoffset = 0;
8215                 rsurface.modelsvector3f_vertexbuffer = 0;
8216                 rsurface.modelsvector3f_bufferoffset = 0;
8217                 rsurface.modeltvector3f_vertexbuffer = 0;
8218                 rsurface.modeltvector3f_bufferoffset = 0;
8219                 rsurface.modelnormal3f_vertexbuffer = 0;
8220                 rsurface.modelnormal3f_bufferoffset = 0;
8221                 rsurface.modelgeneratedvertex = true;
8222         }
8223         else
8224         {
8225                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8226                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8227                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8228                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8229                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8230                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8231                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8232                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8233                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8234                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8235                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8236                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8237                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8238                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8239                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8240                 rsurface.modelgeneratedvertex = false;
8241         }
8242         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8243         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8244         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8245         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8246         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8247         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8248         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8249         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8250         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8251         rsurface.modelelement3i = model->surfmesh.data_element3i;
8252         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8253         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8254         rsurface.modelelement3s = model->surfmesh.data_element3s;
8255         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8256         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8257         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8258         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8259         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8260         rsurface.modelsurfaces = model->data_surfaces;
8261         rsurface.batchgeneratedvertex = false;
8262         rsurface.batchfirstvertex = 0;
8263         rsurface.batchnumvertices = 0;
8264         rsurface.batchfirsttriangle = 0;
8265         rsurface.batchnumtriangles = 0;
8266         rsurface.batchvertex3f  = NULL;
8267         rsurface.batchvertex3f_vertexbuffer = NULL;
8268         rsurface.batchvertex3f_bufferoffset = 0;
8269         rsurface.batchsvector3f = NULL;
8270         rsurface.batchsvector3f_vertexbuffer = NULL;
8271         rsurface.batchsvector3f_bufferoffset = 0;
8272         rsurface.batchtvector3f = NULL;
8273         rsurface.batchtvector3f_vertexbuffer = NULL;
8274         rsurface.batchtvector3f_bufferoffset = 0;
8275         rsurface.batchnormal3f  = NULL;
8276         rsurface.batchnormal3f_vertexbuffer = NULL;
8277         rsurface.batchnormal3f_bufferoffset = 0;
8278         rsurface.batchlightmapcolor4f = NULL;
8279         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8280         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8281         rsurface.batchtexcoordtexture2f = NULL;
8282         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8283         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8284         rsurface.batchtexcoordlightmap2f = NULL;
8285         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8286         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8287         rsurface.batchvertexmesh = NULL;
8288         rsurface.batchvertexmeshbuffer = NULL;
8289         rsurface.batchvertex3fbuffer = NULL;
8290         rsurface.batchelement3i = NULL;
8291         rsurface.batchelement3i_indexbuffer = NULL;
8292         rsurface.batchelement3i_bufferoffset = 0;
8293         rsurface.batchelement3s = NULL;
8294         rsurface.batchelement3s_indexbuffer = NULL;
8295         rsurface.batchelement3s_bufferoffset = 0;
8296         rsurface.passcolor4f = NULL;
8297         rsurface.passcolor4f_vertexbuffer = NULL;
8298         rsurface.passcolor4f_bufferoffset = 0;
8299 }
8300
8301 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)
8302 {
8303         rsurface.entity = r_refdef.scene.worldentity;
8304         rsurface.skeleton = NULL;
8305         rsurface.ent_skinnum = 0;
8306         rsurface.ent_qwskin = -1;
8307         rsurface.ent_flags = entflags;
8308         rsurface.shadertime = r_refdef.scene.time - shadertime;
8309         rsurface.modelnumvertices = numvertices;
8310         rsurface.modelnumtriangles = numtriangles;
8311         rsurface.matrix = *matrix;
8312         rsurface.inversematrix = *inversematrix;
8313         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8314         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8315         R_EntityMatrix(&rsurface.matrix);
8316         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8317         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8318         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8319         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8320         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8321         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8322         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8323         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8324         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8325         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8326         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8327         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8328         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);
8329         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8330         rsurface.frameblend[0].lerp = 1;
8331         rsurface.ent_alttextures = false;
8332         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8333         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8334         if (wanttangents)
8335         {
8336                 rsurface.modelvertex3f = (float *)vertex3f;
8337                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8338                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8339                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8340         }
8341         else if (wantnormals)
8342         {
8343                 rsurface.modelvertex3f = (float *)vertex3f;
8344                 rsurface.modelsvector3f = NULL;
8345                 rsurface.modeltvector3f = NULL;
8346                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347         }
8348         else
8349         {
8350                 rsurface.modelvertex3f = (float *)vertex3f;
8351                 rsurface.modelsvector3f = NULL;
8352                 rsurface.modeltvector3f = NULL;
8353                 rsurface.modelnormal3f = NULL;
8354         }
8355         rsurface.modelvertexmesh = NULL;
8356         rsurface.modelvertexmeshbuffer = NULL;
8357         rsurface.modelvertex3fbuffer = NULL;
8358         rsurface.modelvertex3f_vertexbuffer = 0;
8359         rsurface.modelvertex3f_bufferoffset = 0;
8360         rsurface.modelsvector3f_vertexbuffer = 0;
8361         rsurface.modelsvector3f_bufferoffset = 0;
8362         rsurface.modeltvector3f_vertexbuffer = 0;
8363         rsurface.modeltvector3f_bufferoffset = 0;
8364         rsurface.modelnormal3f_vertexbuffer = 0;
8365         rsurface.modelnormal3f_bufferoffset = 0;
8366         rsurface.modelgeneratedvertex = true;
8367         rsurface.modellightmapcolor4f  = (float *)color4f;
8368         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8369         rsurface.modellightmapcolor4f_bufferoffset = 0;
8370         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8371         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8372         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8373         rsurface.modeltexcoordlightmap2f  = NULL;
8374         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8375         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8376         rsurface.modelelement3i = (int *)element3i;
8377         rsurface.modelelement3i_indexbuffer = NULL;
8378         rsurface.modelelement3i_bufferoffset = 0;
8379         rsurface.modelelement3s = (unsigned short *)element3s;
8380         rsurface.modelelement3s_indexbuffer = NULL;
8381         rsurface.modelelement3s_bufferoffset = 0;
8382         rsurface.modellightmapoffsets = NULL;
8383         rsurface.modelsurfaces = NULL;
8384         rsurface.batchgeneratedvertex = false;
8385         rsurface.batchfirstvertex = 0;
8386         rsurface.batchnumvertices = 0;
8387         rsurface.batchfirsttriangle = 0;
8388         rsurface.batchnumtriangles = 0;
8389         rsurface.batchvertex3f  = NULL;
8390         rsurface.batchvertex3f_vertexbuffer = NULL;
8391         rsurface.batchvertex3f_bufferoffset = 0;
8392         rsurface.batchsvector3f = NULL;
8393         rsurface.batchsvector3f_vertexbuffer = NULL;
8394         rsurface.batchsvector3f_bufferoffset = 0;
8395         rsurface.batchtvector3f = NULL;
8396         rsurface.batchtvector3f_vertexbuffer = NULL;
8397         rsurface.batchtvector3f_bufferoffset = 0;
8398         rsurface.batchnormal3f  = NULL;
8399         rsurface.batchnormal3f_vertexbuffer = NULL;
8400         rsurface.batchnormal3f_bufferoffset = 0;
8401         rsurface.batchlightmapcolor4f = NULL;
8402         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8403         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8404         rsurface.batchtexcoordtexture2f = NULL;
8405         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8406         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8407         rsurface.batchtexcoordlightmap2f = NULL;
8408         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8409         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8410         rsurface.batchvertexmesh = NULL;
8411         rsurface.batchvertexmeshbuffer = NULL;
8412         rsurface.batchvertex3fbuffer = NULL;
8413         rsurface.batchelement3i = NULL;
8414         rsurface.batchelement3i_indexbuffer = NULL;
8415         rsurface.batchelement3i_bufferoffset = 0;
8416         rsurface.batchelement3s = NULL;
8417         rsurface.batchelement3s_indexbuffer = NULL;
8418         rsurface.batchelement3s_bufferoffset = 0;
8419         rsurface.passcolor4f = NULL;
8420         rsurface.passcolor4f_vertexbuffer = NULL;
8421         rsurface.passcolor4f_bufferoffset = 0;
8422
8423         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8424         {
8425                 if ((wantnormals || wanttangents) && !normal3f)
8426                 {
8427                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8428                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8429                 }
8430                 if (wanttangents && !svector3f)
8431                 {
8432                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8434                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8435                 }
8436         }
8437 }
8438
8439 float RSurf_FogPoint(const float *v)
8440 {
8441         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8442         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8443         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8444         float FogHeightFade = r_refdef.fogheightfade;
8445         float fogfrac;
8446         unsigned int fogmasktableindex;
8447         if (r_refdef.fogplaneviewabove)
8448                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8449         else
8450                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8451         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8452         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8453 }
8454
8455 float RSurf_FogVertex(const float *v)
8456 {
8457         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8458         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8459         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8460         float FogHeightFade = rsurface.fogheightfade;
8461         float fogfrac;
8462         unsigned int fogmasktableindex;
8463         if (r_refdef.fogplaneviewabove)
8464                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8465         else
8466                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8467         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8468         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8469 }
8470
8471 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8472 {
8473         int i;
8474         for (i = 0;i < numelements;i++)
8475                 outelement3i[i] = inelement3i[i] + adjust;
8476 }
8477
8478 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8479 extern cvar_t gl_vbo;
8480 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8481 {
8482         int deformindex;
8483         int firsttriangle;
8484         int numtriangles;
8485         int firstvertex;
8486         int endvertex;
8487         int numvertices;
8488         int surfacefirsttriangle;
8489         int surfacenumtriangles;
8490         int surfacefirstvertex;
8491         int surfaceendvertex;
8492         int surfacenumvertices;
8493         int batchnumvertices;
8494         int batchnumtriangles;
8495         int needsupdate;
8496         int i, j;
8497         qboolean gaps;
8498         qboolean dynamicvertex;
8499         float amplitude;
8500         float animpos;
8501         float scale;
8502         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8503         float waveparms[4];
8504         q3shaderinfo_deform_t *deform;
8505         const msurface_t *surface, *firstsurface;
8506         r_vertexmesh_t *vertexmesh;
8507         if (!texturenumsurfaces)
8508                 return;
8509         // find vertex range of this surface batch
8510         gaps = false;
8511         firstsurface = texturesurfacelist[0];
8512         firsttriangle = firstsurface->num_firsttriangle;
8513         batchnumvertices = 0;
8514         batchnumtriangles = 0;
8515         firstvertex = endvertex = firstsurface->num_firstvertex;
8516         for (i = 0;i < texturenumsurfaces;i++)
8517         {
8518                 surface = texturesurfacelist[i];
8519                 if (surface != firstsurface + i)
8520                         gaps = true;
8521                 surfacefirstvertex = surface->num_firstvertex;
8522                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8523                 surfacenumvertices = surface->num_vertices;
8524                 surfacenumtriangles = surface->num_triangles;
8525                 if (firstvertex > surfacefirstvertex)
8526                         firstvertex = surfacefirstvertex;
8527                 if (endvertex < surfaceendvertex)
8528                         endvertex = surfaceendvertex;
8529                 batchnumvertices += surfacenumvertices;
8530                 batchnumtriangles += surfacenumtriangles;
8531         }
8532
8533         // we now know the vertex range used, and if there are any gaps in it
8534         rsurface.batchfirstvertex = firstvertex;
8535         rsurface.batchnumvertices = endvertex - firstvertex;
8536         rsurface.batchfirsttriangle = firsttriangle;
8537         rsurface.batchnumtriangles = batchnumtriangles;
8538
8539         // this variable holds flags for which properties have been updated that
8540         // may require regenerating vertexmesh array...
8541         needsupdate = 0;
8542
8543         // check if any dynamic vertex processing must occur
8544         dynamicvertex = false;
8545
8546         // if there is a chance of animated vertex colors, it's a dynamic batch
8547         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8548         {
8549                 dynamicvertex = true;
8550                 batchneed |= BATCHNEED_NOGAPS;
8551                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8552         }
8553
8554         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8555         {
8556                 switch (deform->deform)
8557                 {
8558                 default:
8559                 case Q3DEFORM_PROJECTIONSHADOW:
8560                 case Q3DEFORM_TEXT0:
8561                 case Q3DEFORM_TEXT1:
8562                 case Q3DEFORM_TEXT2:
8563                 case Q3DEFORM_TEXT3:
8564                 case Q3DEFORM_TEXT4:
8565                 case Q3DEFORM_TEXT5:
8566                 case Q3DEFORM_TEXT6:
8567                 case Q3DEFORM_TEXT7:
8568                 case Q3DEFORM_NONE:
8569                         break;
8570                 case Q3DEFORM_AUTOSPRITE:
8571                         dynamicvertex = true;
8572                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8573                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8574                         break;
8575                 case Q3DEFORM_AUTOSPRITE2:
8576                         dynamicvertex = true;
8577                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8579                         break;
8580                 case Q3DEFORM_NORMAL:
8581                         dynamicvertex = true;
8582                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8583                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8584                         break;
8585                 case Q3DEFORM_WAVE:
8586                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8587                                 break; // if wavefunc is a nop, ignore this transform
8588                         dynamicvertex = true;
8589                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8590                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8591                         break;
8592                 case Q3DEFORM_BULGE:
8593                         dynamicvertex = true;
8594                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8595                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8596                         break;
8597                 case Q3DEFORM_MOVE:
8598                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8599                                 break; // if wavefunc is a nop, ignore this transform
8600                         dynamicvertex = true;
8601                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8602                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8603                         break;
8604                 }
8605         }
8606         switch(rsurface.texture->tcgen.tcgen)
8607         {
8608         default:
8609         case Q3TCGEN_TEXTURE:
8610                 break;
8611         case Q3TCGEN_LIGHTMAP:
8612                 dynamicvertex = true;
8613                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8614                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8615                 break;
8616         case Q3TCGEN_VECTOR:
8617                 dynamicvertex = true;
8618                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8619                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8620                 break;
8621         case Q3TCGEN_ENVIRONMENT:
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8625                 break;
8626         }
8627         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8628         {
8629                 dynamicvertex = true;
8630                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8631                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8632         }
8633
8634         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8635         {
8636                 dynamicvertex = true;
8637                 batchneed |= BATCHNEED_NOGAPS;
8638                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8639         }
8640
8641         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8642         {
8643                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8644                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8645                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8646                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8647                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8648                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8649                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8650         }
8651
8652         // when the model data has no vertex buffer (dynamic mesh), we need to
8653         // eliminate gaps
8654         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8655                 batchneed |= BATCHNEED_NOGAPS;
8656
8657         // if needsupdate, we have to do a dynamic vertex batch for sure
8658         if (needsupdate & batchneed)
8659                 dynamicvertex = true;
8660
8661         // see if we need to build vertexmesh from arrays
8662         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8663                 dynamicvertex = true;
8664
8665         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8666         // also some drivers strongly dislike firstvertex
8667         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8668                 dynamicvertex = true;
8669
8670         rsurface.batchvertex3f = rsurface.modelvertex3f;
8671         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8672         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8673         rsurface.batchsvector3f = rsurface.modelsvector3f;
8674         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8675         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8676         rsurface.batchtvector3f = rsurface.modeltvector3f;
8677         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8678         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8679         rsurface.batchnormal3f = rsurface.modelnormal3f;
8680         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8681         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8682         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8683         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8684         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8685         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8686         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8687         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8688         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8689         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8690         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8691         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8692         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8693         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8694         rsurface.batchelement3i = rsurface.modelelement3i;
8695         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8696         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8697         rsurface.batchelement3s = rsurface.modelelement3s;
8698         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8699         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8700
8701         // if any dynamic vertex processing has to occur in software, we copy the
8702         // entire surface list together before processing to rebase the vertices
8703         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8704         //
8705         // if any gaps exist and we do not have a static vertex buffer, we have to
8706         // copy the surface list together to avoid wasting upload bandwidth on the
8707         // vertices in the gaps.
8708         //
8709         // if gaps exist and we have a static vertex buffer, we still have to
8710         // combine the index buffer ranges into one dynamic index buffer.
8711         //
8712         // in all cases we end up with data that can be drawn in one call.
8713
8714         if (!dynamicvertex)
8715         {
8716                 // static vertex data, just set pointers...
8717                 rsurface.batchgeneratedvertex = false;
8718                 // if there are gaps, we want to build a combined index buffer,
8719                 // otherwise use the original static buffer with an appropriate offset
8720                 if (gaps)
8721                 {
8722                         // build a new triangle elements array for this batch
8723                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8724                         rsurface.batchfirsttriangle = 0;
8725                         numtriangles = 0;
8726                         for (i = 0;i < texturenumsurfaces;i++)
8727                         {
8728                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8729                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8730                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8731                                 numtriangles += surfacenumtriangles;
8732                         }
8733                         rsurface.batchelement3i_indexbuffer = NULL;
8734                         rsurface.batchelement3i_bufferoffset = 0;
8735                         rsurface.batchelement3s = NULL;
8736                         rsurface.batchelement3s_indexbuffer = NULL;
8737                         rsurface.batchelement3s_bufferoffset = 0;
8738                         if (endvertex <= 65536)
8739                         {
8740                                 // make a 16bit (unsigned short) index array if possible
8741                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8742                                 for (i = 0;i < numtriangles*3;i++)
8743                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8744                         }
8745                 }
8746                 return;
8747         }
8748
8749         // something needs software processing, do it for real...
8750         // we only directly handle separate array data in this case and then
8751         // generate interleaved data if needed...
8752         rsurface.batchgeneratedvertex = true;
8753
8754         // now copy the vertex data into a combined array and make an index array
8755         // (this is what Quake3 does all the time)
8756         //if (gaps || rsurface.batchfirstvertex)
8757         {
8758                 rsurface.batchvertex3fbuffer = NULL;
8759                 rsurface.batchvertexmesh = NULL;
8760                 rsurface.batchvertexmeshbuffer = NULL;
8761                 rsurface.batchvertex3f = NULL;
8762                 rsurface.batchvertex3f_vertexbuffer = NULL;
8763                 rsurface.batchvertex3f_bufferoffset = 0;
8764                 rsurface.batchsvector3f = NULL;
8765                 rsurface.batchsvector3f_vertexbuffer = NULL;
8766                 rsurface.batchsvector3f_bufferoffset = 0;
8767                 rsurface.batchtvector3f = NULL;
8768                 rsurface.batchtvector3f_vertexbuffer = NULL;
8769                 rsurface.batchtvector3f_bufferoffset = 0;
8770                 rsurface.batchnormal3f = NULL;
8771                 rsurface.batchnormal3f_vertexbuffer = NULL;
8772                 rsurface.batchnormal3f_bufferoffset = 0;
8773                 rsurface.batchlightmapcolor4f = NULL;
8774                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8775                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8776                 rsurface.batchtexcoordtexture2f = NULL;
8777                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8778                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8779                 rsurface.batchtexcoordlightmap2f = NULL;
8780                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8781                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8782                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8783                 rsurface.batchelement3i_indexbuffer = NULL;
8784                 rsurface.batchelement3i_bufferoffset = 0;
8785                 rsurface.batchelement3s = NULL;
8786                 rsurface.batchelement3s_indexbuffer = NULL;
8787                 rsurface.batchelement3s_bufferoffset = 0;
8788                 // we'll only be setting up certain arrays as needed
8789                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8790                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8791                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8792                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8793                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8794                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8795                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8796                 {
8797                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8799                 }
8800                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8801                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8802                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8803                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8804                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8805                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8806                 numvertices = 0;
8807                 numtriangles = 0;
8808                 for (i = 0;i < texturenumsurfaces;i++)
8809                 {
8810                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8811                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8812                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8813                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8814                         // copy only the data requested
8815                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8816                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8817                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8818                         {
8819                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8820                                 {
8821                                         if (rsurface.batchvertex3f)
8822                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8823                                         else
8824                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8825                                 }
8826                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8827                                 {
8828                                         if (rsurface.modelnormal3f)
8829                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8830                                         else
8831                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8832                                 }
8833                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8834                                 {
8835                                         if (rsurface.modelsvector3f)
8836                                         {
8837                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8838                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8839                                         }
8840                                         else
8841                                         {
8842                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8843                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8844                                         }
8845                                 }
8846                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8847                                 {
8848                                         if (rsurface.modellightmapcolor4f)
8849                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8850                                         else
8851                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8852                                 }
8853                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8854                                 {
8855                                         if (rsurface.modeltexcoordtexture2f)
8856                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8857                                         else
8858                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8859                                 }
8860                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8861                                 {
8862                                         if (rsurface.modeltexcoordlightmap2f)
8863                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8864                                         else
8865                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8866                                 }
8867                         }
8868                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8869                         numvertices += surfacenumvertices;
8870                         numtriangles += surfacenumtriangles;
8871                 }
8872
8873                 // generate a 16bit index array as well if possible
8874                 // (in general, dynamic batches fit)
8875                 if (numvertices <= 65536)
8876                 {
8877                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8878                         for (i = 0;i < numtriangles*3;i++)
8879                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8880                 }
8881
8882                 // since we've copied everything, the batch now starts at 0
8883                 rsurface.batchfirstvertex = 0;
8884                 rsurface.batchnumvertices = batchnumvertices;
8885                 rsurface.batchfirsttriangle = 0;
8886                 rsurface.batchnumtriangles = batchnumtriangles;
8887         }
8888
8889         // q1bsp surfaces rendered in vertex color mode have to have colors
8890         // calculated based on lightstyles
8891         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8892         {
8893                 // generate color arrays for the surfaces in this list
8894                 int c[4];
8895                 int scale;
8896                 int size3;
8897                 const int *offsets;
8898                 const unsigned char *lm;
8899                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8900                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8901                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8902                 numvertices = 0;
8903                 for (i = 0;i < texturenumsurfaces;i++)
8904                 {
8905                         surface = texturesurfacelist[i];
8906                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8907                         surfacenumvertices = surface->num_vertices;
8908                         if (surface->lightmapinfo->samples)
8909                         {
8910                                 for (j = 0;j < surfacenumvertices;j++)
8911                                 {
8912                                         lm = surface->lightmapinfo->samples + offsets[j];
8913                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8914                                         VectorScale(lm, scale, c);
8915                                         if (surface->lightmapinfo->styles[1] != 255)
8916                                         {
8917                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8918                                                 lm += size3;
8919                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8920                                                 VectorMA(c, scale, lm, c);
8921                                                 if (surface->lightmapinfo->styles[2] != 255)
8922                                                 {
8923                                                         lm += size3;
8924                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8925                                                         VectorMA(c, scale, lm, c);
8926                                                         if (surface->lightmapinfo->styles[3] != 255)
8927                                                         {
8928                                                                 lm += size3;
8929                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8930                                                                 VectorMA(c, scale, lm, c);
8931                                                         }
8932                                                 }
8933                                         }
8934                                         c[0] >>= 7;
8935                                         c[1] >>= 7;
8936                                         c[2] >>= 7;
8937                                         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);
8938                                         numvertices++;
8939                                 }
8940                         }
8941                         else
8942                         {
8943                                 for (j = 0;j < surfacenumvertices;j++)
8944                                 {
8945                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8946                                         numvertices++;
8947                                 }
8948                         }
8949                 }
8950         }
8951
8952         // if vertices are deformed (sprite flares and things in maps, possibly
8953         // water waves, bulges and other deformations), modify the copied vertices
8954         // in place
8955         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8956         {
8957                 switch (deform->deform)
8958                 {
8959                 default:
8960                 case Q3DEFORM_PROJECTIONSHADOW:
8961                 case Q3DEFORM_TEXT0:
8962                 case Q3DEFORM_TEXT1:
8963                 case Q3DEFORM_TEXT2:
8964                 case Q3DEFORM_TEXT3:
8965                 case Q3DEFORM_TEXT4:
8966                 case Q3DEFORM_TEXT5:
8967                 case Q3DEFORM_TEXT6:
8968                 case Q3DEFORM_TEXT7:
8969                 case Q3DEFORM_NONE:
8970                         break;
8971                 case Q3DEFORM_AUTOSPRITE:
8972                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8973                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8974                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8975                         VectorNormalize(newforward);
8976                         VectorNormalize(newright);
8977                         VectorNormalize(newup);
8978 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8979 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8980 //                      rsurface.batchvertex3f_bufferoffset = 0;
8981 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8982 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8983 //                      rsurface.batchsvector3f_bufferoffset = 0;
8984 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8985 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8986 //                      rsurface.batchtvector3f_bufferoffset = 0;
8987 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8988 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8989 //                      rsurface.batchnormal3f_bufferoffset = 0;
8990                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8991                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8992                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8993                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8994                                 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);
8995                         // a single autosprite surface can contain multiple sprites...
8996                         for (j = 0;j < batchnumvertices - 3;j += 4)
8997                         {
8998                                 VectorClear(center);
8999                                 for (i = 0;i < 4;i++)
9000                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9001                                 VectorScale(center, 0.25f, center);
9002                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9003                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9004                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9005                                 for (i = 0;i < 4;i++)
9006                                 {
9007                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9008                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9009                                 }
9010                         }
9011                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9012                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9013                         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);
9014                         break;
9015                 case Q3DEFORM_AUTOSPRITE2:
9016                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9017                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9018                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9019                         VectorNormalize(newforward);
9020                         VectorNormalize(newright);
9021                         VectorNormalize(newup);
9022 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9023 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9024 //                      rsurface.batchvertex3f_bufferoffset = 0;
9025                         {
9026                                 const float *v1, *v2;
9027                                 vec3_t start, end;
9028                                 float f, l;
9029                                 struct
9030                                 {
9031                                         float length2;
9032                                         const float *v1;
9033                                         const float *v2;
9034                                 }
9035                                 shortest[2];
9036                                 memset(shortest, 0, sizeof(shortest));
9037                                 // a single autosprite surface can contain multiple sprites...
9038                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9039                                 {
9040                                         VectorClear(center);
9041                                         for (i = 0;i < 4;i++)
9042                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9043                                         VectorScale(center, 0.25f, center);
9044                                         // find the two shortest edges, then use them to define the
9045                                         // axis vectors for rotating around the central axis
9046                                         for (i = 0;i < 6;i++)
9047                                         {
9048                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9049                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9050                                                 l = VectorDistance2(v1, v2);
9051                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9052                                                 if (v1[2] != v2[2])
9053                                                         l += (1.0f / 1024.0f);
9054                                                 if (shortest[0].length2 > l || i == 0)
9055                                                 {
9056                                                         shortest[1] = shortest[0];
9057                                                         shortest[0].length2 = l;
9058                                                         shortest[0].v1 = v1;
9059                                                         shortest[0].v2 = v2;
9060                                                 }
9061                                                 else if (shortest[1].length2 > l || i == 1)
9062                                                 {
9063                                                         shortest[1].length2 = l;
9064                                                         shortest[1].v1 = v1;
9065                                                         shortest[1].v2 = v2;
9066                                                 }
9067                                         }
9068                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9069                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9070                                         // this calculates the right vector from the shortest edge
9071                                         // and the up vector from the edge midpoints
9072                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9073                                         VectorNormalize(right);
9074                                         VectorSubtract(end, start, up);
9075                                         VectorNormalize(up);
9076                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9077                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9078                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9079                                         VectorNegate(forward, forward);
9080                                         VectorReflect(forward, 0, up, forward);
9081                                         VectorNormalize(forward);
9082                                         CrossProduct(up, forward, newright);
9083                                         VectorNormalize(newright);
9084                                         // rotate the quad around the up axis vector, this is made
9085                                         // especially easy by the fact we know the quad is flat,
9086                                         // so we only have to subtract the center position and
9087                                         // measure distance along the right vector, and then
9088                                         // multiply that by the newright vector and add back the
9089                                         // center position
9090                                         // we also need to subtract the old position to undo the
9091                                         // displacement from the center, which we do with a
9092                                         // DotProduct, the subtraction/addition of center is also
9093                                         // optimized into DotProducts here
9094                                         l = DotProduct(right, center);
9095                                         for (i = 0;i < 4;i++)
9096                                         {
9097                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9098                                                 f = DotProduct(right, v1) - l;
9099                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9100                                         }
9101                                 }
9102                         }
9103                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9104                         {
9105 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9106 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9107 //                              rsurface.batchnormal3f_bufferoffset = 0;
9108                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9109                         }
9110                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9111                         {
9112 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9113 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9114 //                              rsurface.batchsvector3f_bufferoffset = 0;
9115 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9116 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9117 //                              rsurface.batchtvector3f_bufferoffset = 0;
9118                                 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);
9119                         }
9120                         break;
9121                 case Q3DEFORM_NORMAL:
9122                         // deform the normals to make reflections wavey
9123                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9124                         rsurface.batchnormal3f_vertexbuffer = NULL;
9125                         rsurface.batchnormal3f_bufferoffset = 0;
9126                         for (j = 0;j < batchnumvertices;j++)
9127                         {
9128                                 float vertex[3];
9129                                 float *normal = rsurface.batchnormal3f + 3*j;
9130                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9131                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9132                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9133                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9134                                 VectorNormalize(normal);
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_WAVE:
9148                         // deform vertex array to make wavey water and flags and such
9149                         waveparms[0] = deform->waveparms[0];
9150                         waveparms[1] = deform->waveparms[1];
9151                         waveparms[2] = deform->waveparms[2];
9152                         waveparms[3] = deform->waveparms[3];
9153                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9154                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9155                         // this is how a divisor of vertex influence on deformation
9156                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9157                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9158 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9159 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9160 //                      rsurface.batchvertex3f_bufferoffset = 0;
9161 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9162 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9163 //                      rsurface.batchnormal3f_bufferoffset = 0;
9164                         for (j = 0;j < batchnumvertices;j++)
9165                         {
9166                                 // if the wavefunc depends on time, evaluate it per-vertex
9167                                 if (waveparms[3])
9168                                 {
9169                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9170                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9171                                 }
9172                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9173                         }
9174                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9175                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9176                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9177                         {
9178 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9179 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9180 //                              rsurface.batchsvector3f_bufferoffset = 0;
9181 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9182 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9183 //                              rsurface.batchtvector3f_bufferoffset = 0;
9184                                 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);
9185                         }
9186                         break;
9187                 case Q3DEFORM_BULGE:
9188                         // deform vertex array to make the surface have moving bulges
9189 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9190 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9191 //                      rsurface.batchvertex3f_bufferoffset = 0;
9192 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9193 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9194 //                      rsurface.batchnormal3f_bufferoffset = 0;
9195                         for (j = 0;j < batchnumvertices;j++)
9196                         {
9197                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
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_MOVE:
9214                         // deform vertex array
9215                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9216                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9217                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9218                         VectorScale(deform->parms, scale, waveparms);
9219 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9220 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9221 //                      rsurface.batchvertex3f_bufferoffset = 0;
9222                         for (j = 0;j < batchnumvertices;j++)
9223                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9224                         break;
9225                 }
9226         }
9227
9228         // generate texcoords based on the chosen texcoord source
9229         switch(rsurface.texture->tcgen.tcgen)
9230         {
9231         default:
9232         case Q3TCGEN_TEXTURE:
9233                 break;
9234         case Q3TCGEN_LIGHTMAP:
9235 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9236 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9237 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9238                 if (rsurface.batchtexcoordlightmap2f)
9239                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9240                 break;
9241         case Q3TCGEN_VECTOR:
9242 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9243 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9244 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9245                 for (j = 0;j < batchnumvertices;j++)
9246                 {
9247                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9248                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9249                 }
9250                 break;
9251         case Q3TCGEN_ENVIRONMENT:
9252                 // make environment reflections using a spheremap
9253                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9254                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9255                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9256                 for (j = 0;j < batchnumvertices;j++)
9257                 {
9258                         // identical to Q3A's method, but executed in worldspace so
9259                         // carried models can be shiny too
9260
9261                         float viewer[3], d, reflected[3], worldreflected[3];
9262
9263                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9264                         // VectorNormalize(viewer);
9265
9266                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9267
9268                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9269                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9270                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9271                         // note: this is proportinal to viewer, so we can normalize later
9272
9273                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9274                         VectorNormalize(worldreflected);
9275
9276                         // note: this sphere map only uses world x and z!
9277                         // so positive and negative y will LOOK THE SAME.
9278                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9279                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9280                 }
9281                 break;
9282         }
9283         // the only tcmod that needs software vertex processing is turbulent, so
9284         // check for it here and apply the changes if needed
9285         // and we only support that as the first one
9286         // (handling a mixture of turbulent and other tcmods would be problematic
9287         //  without punting it entirely to a software path)
9288         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9289         {
9290                 amplitude = rsurface.texture->tcmods[0].parms[1];
9291                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9292 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9293 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9294 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9295                 for (j = 0;j < batchnumvertices;j++)
9296                 {
9297                         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);
9298                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9299                 }
9300         }
9301
9302         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9303         {
9304                 // convert the modified arrays to vertex structs
9305 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9306 //              rsurface.batchvertexmeshbuffer = NULL;
9307                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9308                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9309                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9310                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9311                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9312                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9313                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9314                 {
9315                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9316                         {
9317                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9318                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9319                         }
9320                 }
9321                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9322                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9323                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9324                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9325                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9326                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9327                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9328                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9329                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9330         }
9331 }
9332
9333 void RSurf_DrawBatch(void)
9334 {
9335         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9336         // through the pipeline, killing it earlier in the pipeline would have
9337         // per-surface overhead rather than per-batch overhead, so it's best to
9338         // reject it here, before it hits glDraw.
9339         if (rsurface.batchnumtriangles == 0)
9340                 return;
9341 #if 0
9342         // batch debugging code
9343         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9344         {
9345                 int i;
9346                 int j;
9347                 int c;
9348                 const int *e;
9349                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9350                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9351                 {
9352                         c = e[i];
9353                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9354                         {
9355                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9356                                 {
9357                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9358                                                 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);
9359                                         break;
9360                                 }
9361                         }
9362                 }
9363         }
9364 #endif
9365         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);
9366 }
9367
9368 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9369 {
9370         // pick the closest matching water plane
9371         int planeindex, vertexindex, bestplaneindex = -1;
9372         float d, bestd;
9373         vec3_t vert;
9374         const float *v;
9375         r_waterstate_waterplane_t *p;
9376         qboolean prepared = false;
9377         bestd = 0;
9378         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9379         {
9380                 if(p->camera_entity != rsurface.texture->camera_entity)
9381                         continue;
9382                 d = 0;
9383                 if(!prepared)
9384                 {
9385                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9386                         prepared = true;
9387                         if(rsurface.batchnumvertices == 0)
9388                                 break;
9389                 }
9390                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9391                 {
9392                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9393                         d += fabs(PlaneDiff(vert, &p->plane));
9394                 }
9395                 if (bestd > d || bestplaneindex < 0)
9396                 {
9397                         bestd = d;
9398                         bestplaneindex = planeindex;
9399                 }
9400         }
9401         return bestplaneindex;
9402         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9403         // this situation though, as it might be better to render single larger
9404         // batches with useless stuff (backface culled for example) than to
9405         // render multiple smaller batches
9406 }
9407
9408 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9409 {
9410         int i;
9411         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9412         rsurface.passcolor4f_vertexbuffer = 0;
9413         rsurface.passcolor4f_bufferoffset = 0;
9414         for (i = 0;i < rsurface.batchnumvertices;i++)
9415                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9416 }
9417
9418 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9419 {
9420         int i;
9421         float f;
9422         const float *v;
9423         const float *c;
9424         float *c2;
9425         if (rsurface.passcolor4f)
9426         {
9427                 // generate color arrays
9428                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9429                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9430                 rsurface.passcolor4f_vertexbuffer = 0;
9431                 rsurface.passcolor4f_bufferoffset = 0;
9432                 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)
9433                 {
9434                         f = RSurf_FogVertex(v);
9435                         c2[0] = c[0] * f;
9436                         c2[1] = c[1] * f;
9437                         c2[2] = c[2] * f;
9438                         c2[3] = c[3];
9439                 }
9440         }
9441         else
9442         {
9443                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9444                 rsurface.passcolor4f_vertexbuffer = 0;
9445                 rsurface.passcolor4f_bufferoffset = 0;
9446                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9447                 {
9448                         f = RSurf_FogVertex(v);
9449                         c2[0] = f;
9450                         c2[1] = f;
9451                         c2[2] = f;
9452                         c2[3] = 1;
9453                 }
9454         }
9455 }
9456
9457 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9458 {
9459         int i;
9460         float f;
9461         const float *v;
9462         const float *c;
9463         float *c2;
9464         if (!rsurface.passcolor4f)
9465                 return;
9466         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9467         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9468         rsurface.passcolor4f_vertexbuffer = 0;
9469         rsurface.passcolor4f_bufferoffset = 0;
9470         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)
9471         {
9472                 f = RSurf_FogVertex(v);
9473                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9474                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9475                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9476                 c2[3] = c[3];
9477         }
9478 }
9479
9480 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9481 {
9482         int i;
9483         const float *c;
9484         float *c2;
9485         if (!rsurface.passcolor4f)
9486                 return;
9487         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9488         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9489         rsurface.passcolor4f_vertexbuffer = 0;
9490         rsurface.passcolor4f_bufferoffset = 0;
9491         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9492         {
9493                 c2[0] = c[0] * r;
9494                 c2[1] = c[1] * g;
9495                 c2[2] = c[2] * b;
9496                 c2[3] = c[3] * a;
9497         }
9498 }
9499
9500 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9501 {
9502         int i;
9503         const float *c;
9504         float *c2;
9505         if (!rsurface.passcolor4f)
9506                 return;
9507         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9508         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9509         rsurface.passcolor4f_vertexbuffer = 0;
9510         rsurface.passcolor4f_bufferoffset = 0;
9511         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9512         {
9513                 c2[0] = c[0] + r_refdef.scene.ambient;
9514                 c2[1] = c[1] + r_refdef.scene.ambient;
9515                 c2[2] = c[2] + r_refdef.scene.ambient;
9516                 c2[3] = c[3];
9517         }
9518 }
9519
9520 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9521 {
9522         // TODO: optimize
9523         rsurface.passcolor4f = NULL;
9524         rsurface.passcolor4f_vertexbuffer = 0;
9525         rsurface.passcolor4f_bufferoffset = 0;
9526         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9527         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9528         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9529         GL_Color(r, g, b, a);
9530         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9531         RSurf_DrawBatch();
9532 }
9533
9534 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9535 {
9536         // TODO: optimize applyfog && applycolor case
9537         // just apply fog if necessary, and tint the fog color array if necessary
9538         rsurface.passcolor4f = NULL;
9539         rsurface.passcolor4f_vertexbuffer = 0;
9540         rsurface.passcolor4f_bufferoffset = 0;
9541         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9542         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9543         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9544         GL_Color(r, g, b, a);
9545         RSurf_DrawBatch();
9546 }
9547
9548 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9549 {
9550         // TODO: optimize
9551         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9552         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9553         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9554         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9555         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9556         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9557         GL_Color(r, g, b, a);
9558         RSurf_DrawBatch();
9559 }
9560
9561 static void RSurf_DrawBatch_GL11_ClampColor(void)
9562 {
9563         int i;
9564         const float *c1;
9565         float *c2;
9566         if (!rsurface.passcolor4f)
9567                 return;
9568         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9569         {
9570                 c2[0] = bound(0.0f, c1[0], 1.0f);
9571                 c2[1] = bound(0.0f, c1[1], 1.0f);
9572                 c2[2] = bound(0.0f, c1[2], 1.0f);
9573                 c2[3] = bound(0.0f, c1[3], 1.0f);
9574         }
9575 }
9576
9577 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9578 {
9579         int i;
9580         float f;
9581         const float *v;
9582         const float *n;
9583         float *c;
9584         //vec3_t eyedir;
9585
9586         // fake shading
9587         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9588         rsurface.passcolor4f_vertexbuffer = 0;
9589         rsurface.passcolor4f_bufferoffset = 0;
9590         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)
9591         {
9592                 f = -DotProduct(r_refdef.view.forward, n);
9593                 f = max(0, f);
9594                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9595                 f *= r_refdef.lightmapintensity;
9596                 Vector4Set(c, f, f, f, 1);
9597         }
9598 }
9599
9600 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9601 {
9602         RSurf_DrawBatch_GL11_ApplyFakeLight();
9603         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9604         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9605         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9606         GL_Color(r, g, b, a);
9607         RSurf_DrawBatch();
9608 }
9609
9610 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9611 {
9612         int i;
9613         float f;
9614         float alpha;
9615         const float *v;
9616         const float *n;
9617         float *c;
9618         vec3_t ambientcolor;
9619         vec3_t diffusecolor;
9620         vec3_t lightdir;
9621         // TODO: optimize
9622         // model lighting
9623         VectorCopy(rsurface.modellight_lightdir, lightdir);
9624         f = 0.5f * r_refdef.lightmapintensity;
9625         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9626         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9627         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9628         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9629         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9630         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9631         alpha = *a;
9632         if (VectorLength2(diffusecolor) > 0)
9633         {
9634                 // q3-style directional shading
9635                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9636                 rsurface.passcolor4f_vertexbuffer = 0;
9637                 rsurface.passcolor4f_bufferoffset = 0;
9638                 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)
9639                 {
9640                         if ((f = DotProduct(n, lightdir)) > 0)
9641                                 VectorMA(ambientcolor, f, diffusecolor, c);
9642                         else
9643                                 VectorCopy(ambientcolor, c);
9644                         c[3] = alpha;
9645                 }
9646                 *r = 1;
9647                 *g = 1;
9648                 *b = 1;
9649                 *a = 1;
9650                 *applycolor = false;
9651         }
9652         else
9653         {
9654                 *r = ambientcolor[0];
9655                 *g = ambientcolor[1];
9656                 *b = ambientcolor[2];
9657                 rsurface.passcolor4f = NULL;
9658                 rsurface.passcolor4f_vertexbuffer = 0;
9659                 rsurface.passcolor4f_bufferoffset = 0;
9660         }
9661 }
9662
9663 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9664 {
9665         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9666         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9667         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9668         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9669         GL_Color(r, g, b, a);
9670         RSurf_DrawBatch();
9671 }
9672
9673 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9674 {
9675         int i;
9676         float f;
9677         const float *v;
9678         float *c;
9679
9680         // fake shading
9681         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9682         rsurface.passcolor4f_vertexbuffer = 0;
9683         rsurface.passcolor4f_bufferoffset = 0;
9684
9685         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9686         {
9687                 f = 1 - RSurf_FogVertex(v);
9688                 c[0] = r;
9689                 c[1] = g;
9690                 c[2] = b;
9691                 c[3] = f * a;
9692         }
9693 }
9694
9695 void RSurf_SetupDepthAndCulling(void)
9696 {
9697         // submodels are biased to avoid z-fighting with world surfaces that they
9698         // may be exactly overlapping (avoids z-fighting artifacts on certain
9699         // doors and things in Quake maps)
9700         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9701         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9702         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9703         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9704 }
9705
9706 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9707 {
9708         // transparent sky would be ridiculous
9709         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9710                 return;
9711         R_SetupShader_Generic_NoTexture(false, false);
9712         skyrenderlater = true;
9713         RSurf_SetupDepthAndCulling();
9714         GL_DepthMask(true);
9715         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9716         // skymasking on them, and Quake3 never did sky masking (unlike
9717         // software Quake and software Quake2), so disable the sky masking
9718         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9719         // and skymasking also looks very bad when noclipping outside the
9720         // level, so don't use it then either.
9721         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9722         {
9723                 R_Mesh_ResetTextureState();
9724                 if (skyrendermasked)
9725                 {
9726                         R_SetupShader_DepthOrShadow(false);
9727                         // depth-only (masking)
9728                         GL_ColorMask(0,0,0,0);
9729                         // just to make sure that braindead drivers don't draw
9730                         // anything despite that colormask...
9731                         GL_BlendFunc(GL_ZERO, GL_ONE);
9732                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9733                         if (rsurface.batchvertex3fbuffer)
9734                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9735                         else
9736                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9737                 }
9738                 else
9739                 {
9740                         R_SetupShader_Generic_NoTexture(false, false);
9741                         // fog sky
9742                         GL_BlendFunc(GL_ONE, GL_ZERO);
9743                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9744                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9745                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9746                 }
9747                 RSurf_DrawBatch();
9748                 if (skyrendermasked)
9749                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9750         }
9751         R_Mesh_ResetTextureState();
9752         GL_Color(1, 1, 1, 1);
9753 }
9754
9755 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9756 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9757 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9758 {
9759         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9760                 return;
9761         if (prepass)
9762         {
9763                 // render screenspace normalmap to texture
9764                 GL_DepthMask(true);
9765                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9766                 RSurf_DrawBatch();
9767         }
9768
9769         // bind lightmap texture
9770
9771         // water/refraction/reflection/camera surfaces have to be handled specially
9772         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9773         {
9774                 int start, end, startplaneindex;
9775                 for (start = 0;start < texturenumsurfaces;start = end)
9776                 {
9777                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9778                         if(startplaneindex < 0)
9779                         {
9780                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9781                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9782                                 end = start + 1;
9783                                 continue;
9784                         }
9785                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9786                                 ;
9787                         // now that we have a batch using the same planeindex, render it
9788                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9789                         {
9790                                 // render water or distortion background
9791                                 GL_DepthMask(true);
9792                                 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);
9793                                 RSurf_DrawBatch();
9794                                 // blend surface on top
9795                                 GL_DepthMask(false);
9796                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9797                                 RSurf_DrawBatch();
9798                         }
9799                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9800                         {
9801                                 // render surface with reflection texture as input
9802                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9803                                 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);
9804                                 RSurf_DrawBatch();
9805                         }
9806                 }
9807                 return;
9808         }
9809
9810         // render surface batch normally
9811         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9812         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);
9813         RSurf_DrawBatch();
9814 }
9815
9816 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9817 {
9818         // OpenGL 1.3 path - anything not completely ancient
9819         qboolean applycolor;
9820         qboolean applyfog;
9821         int layerindex;
9822         const texturelayer_t *layer;
9823         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);
9824         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9825
9826         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9827         {
9828                 vec4_t layercolor;
9829                 int layertexrgbscale;
9830                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9831                 {
9832                         if (layerindex == 0)
9833                                 GL_AlphaTest(true);
9834                         else
9835                         {
9836                                 GL_AlphaTest(false);
9837                                 GL_DepthFunc(GL_EQUAL);
9838                         }
9839                 }
9840                 GL_DepthMask(layer->depthmask && writedepth);
9841                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9842                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9843                 {
9844                         layertexrgbscale = 4;
9845                         VectorScale(layer->color, 0.25f, layercolor);
9846                 }
9847                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9848                 {
9849                         layertexrgbscale = 2;
9850                         VectorScale(layer->color, 0.5f, layercolor);
9851                 }
9852                 else
9853                 {
9854                         layertexrgbscale = 1;
9855                         VectorScale(layer->color, 1.0f, layercolor);
9856                 }
9857                 layercolor[3] = layer->color[3];
9858                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9859                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9860                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9861                 switch (layer->type)
9862                 {
9863                 case TEXTURELAYERTYPE_LITTEXTURE:
9864                         // single-pass lightmapped texture with 2x rgbscale
9865                         R_Mesh_TexBind(0, r_texture_white);
9866                         R_Mesh_TexMatrix(0, NULL);
9867                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9868                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9869                         R_Mesh_TexBind(1, layer->texture);
9870                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9871                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9873                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9874                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9875                         else if (FAKELIGHT_ENABLED)
9876                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9877                         else if (rsurface.uselightmaptexture)
9878                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9879                         else
9880                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9881                         break;
9882                 case TEXTURELAYERTYPE_TEXTURE:
9883                         // singletexture unlit texture with transparency support
9884                         R_Mesh_TexBind(0, layer->texture);
9885                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9886                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9887                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9888                         R_Mesh_TexBind(1, 0);
9889                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9890                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9891                         break;
9892                 case TEXTURELAYERTYPE_FOG:
9893                         // singletexture fogging
9894                         if (layer->texture)
9895                         {
9896                                 R_Mesh_TexBind(0, layer->texture);
9897                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9898                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9899                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9900                         }
9901                         else
9902                         {
9903                                 R_Mesh_TexBind(0, 0);
9904                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9905                         }
9906                         R_Mesh_TexBind(1, 0);
9907                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9908                         // generate a color array for the fog pass
9909                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9910                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9911                         RSurf_DrawBatch();
9912                         break;
9913                 default:
9914                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9915                 }
9916         }
9917         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9918         {
9919                 GL_DepthFunc(GL_LEQUAL);
9920                 GL_AlphaTest(false);
9921         }
9922 }
9923
9924 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9925 {
9926         // OpenGL 1.1 - crusty old voodoo path
9927         qboolean applyfog;
9928         int layerindex;
9929         const texturelayer_t *layer;
9930         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);
9931         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9932
9933         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9934         {
9935                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9936                 {
9937                         if (layerindex == 0)
9938                                 GL_AlphaTest(true);
9939                         else
9940                         {
9941                                 GL_AlphaTest(false);
9942                                 GL_DepthFunc(GL_EQUAL);
9943                         }
9944                 }
9945                 GL_DepthMask(layer->depthmask && writedepth);
9946                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9947                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9948                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9949                 switch (layer->type)
9950                 {
9951                 case TEXTURELAYERTYPE_LITTEXTURE:
9952                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9953                         {
9954                                 // two-pass lit texture with 2x rgbscale
9955                                 // first the lightmap pass
9956                                 R_Mesh_TexBind(0, r_texture_white);
9957                                 R_Mesh_TexMatrix(0, NULL);
9958                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9960                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9961                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9962                                 else if (FAKELIGHT_ENABLED)
9963                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9964                                 else if (rsurface.uselightmaptexture)
9965                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9966                                 else
9967                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9968                                 // then apply the texture to it
9969                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9970                                 R_Mesh_TexBind(0, layer->texture);
9971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9974                                 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);
9975                         }
9976                         else
9977                         {
9978                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9979                                 R_Mesh_TexBind(0, layer->texture);
9980                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9983                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9984                                         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);
9985                                 else
9986                                         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);
9987                         }
9988                         break;
9989                 case TEXTURELAYERTYPE_TEXTURE:
9990                         // singletexture unlit texture with transparency support
9991                         R_Mesh_TexBind(0, layer->texture);
9992                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9993                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9994                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9995                         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);
9996                         break;
9997                 case TEXTURELAYERTYPE_FOG:
9998                         // singletexture fogging
9999                         if (layer->texture)
10000                         {
10001                                 R_Mesh_TexBind(0, layer->texture);
10002                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10003                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10004                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10005                         }
10006                         else
10007                         {
10008                                 R_Mesh_TexBind(0, 0);
10009                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10010                         }
10011                         // generate a color array for the fog pass
10012                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10013                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10014                         RSurf_DrawBatch();
10015                         break;
10016                 default:
10017                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10018                 }
10019         }
10020         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10021         {
10022                 GL_DepthFunc(GL_LEQUAL);
10023                 GL_AlphaTest(false);
10024         }
10025 }
10026
10027 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10028 {
10029         int vi;
10030         int j;
10031         r_vertexgeneric_t *batchvertex;
10032         float c[4];
10033
10034 //      R_Mesh_ResetTextureState();
10035         R_SetupShader_Generic_NoTexture(false, false);
10036
10037         if(rsurface.texture && rsurface.texture->currentskinframe)
10038         {
10039                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10040                 c[3] *= rsurface.texture->currentalpha;
10041         }
10042         else
10043         {
10044                 c[0] = 1;
10045                 c[1] = 0;
10046                 c[2] = 1;
10047                 c[3] = 1;
10048         }
10049
10050         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10051         {
10052                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10053                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10054                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10055         }
10056
10057         // brighten it up (as texture value 127 means "unlit")
10058         c[0] *= 2 * r_refdef.view.colorscale;
10059         c[1] *= 2 * r_refdef.view.colorscale;
10060         c[2] *= 2 * r_refdef.view.colorscale;
10061
10062         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10063                 c[3] *= r_wateralpha.value;
10064
10065         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10066         {
10067                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10068                 GL_DepthMask(false);
10069         }
10070         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10071         {
10072                 GL_BlendFunc(GL_ONE, GL_ONE);
10073                 GL_DepthMask(false);
10074         }
10075         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10076         {
10077                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10078                 GL_DepthMask(false);
10079         }
10080         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10081         {
10082                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10083                 GL_DepthMask(false);
10084         }
10085         else
10086         {
10087                 GL_BlendFunc(GL_ONE, GL_ZERO);
10088                 GL_DepthMask(writedepth);
10089         }
10090
10091         if (r_showsurfaces.integer == 3)
10092         {
10093                 rsurface.passcolor4f = NULL;
10094
10095                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10096                 {
10097                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10098
10099                         rsurface.passcolor4f = NULL;
10100                         rsurface.passcolor4f_vertexbuffer = 0;
10101                         rsurface.passcolor4f_bufferoffset = 0;
10102                 }
10103                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10104                 {
10105                         qboolean applycolor = true;
10106                         float one = 1.0;
10107
10108                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109
10110                         r_refdef.lightmapintensity = 1;
10111                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10112                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10113                 }
10114                 else if (FAKELIGHT_ENABLED)
10115                 {
10116                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10117
10118                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10119                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10120                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10121                 }
10122                 else
10123                 {
10124                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10125
10126                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10127                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10128                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10129                 }
10130
10131                 if(!rsurface.passcolor4f)
10132                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10133
10134                 RSurf_DrawBatch_GL11_ApplyAmbient();
10135                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10136                 if(r_refdef.fogenabled)
10137                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10138                 RSurf_DrawBatch_GL11_ClampColor();
10139
10140                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10141                 R_SetupShader_Generic_NoTexture(false, false);
10142                 RSurf_DrawBatch();
10143         }
10144         else if (!r_refdef.view.showdebug)
10145         {
10146                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10147                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10148                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10149                 {
10150                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10151                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10152                 }
10153                 R_Mesh_PrepareVertices_Generic_Unlock();
10154                 RSurf_DrawBatch();
10155         }
10156         else if (r_showsurfaces.integer == 4)
10157         {
10158                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10159                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10160                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10161                 {
10162                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10163                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10164                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10165                 }
10166                 R_Mesh_PrepareVertices_Generic_Unlock();
10167                 RSurf_DrawBatch();
10168         }
10169         else if (r_showsurfaces.integer == 2)
10170         {
10171                 const int *e;
10172                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10173                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10174                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10175                 {
10176                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10177                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10178                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10179                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10180                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10181                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10182                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10183                 }
10184                 R_Mesh_PrepareVertices_Generic_Unlock();
10185                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10186         }
10187         else
10188         {
10189                 int texturesurfaceindex;
10190                 int k;
10191                 const msurface_t *surface;
10192                 float surfacecolor4f[4];
10193                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10194                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10195                 vi = 0;
10196                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10197                 {
10198                         surface = texturesurfacelist[texturesurfaceindex];
10199                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10200                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10201                         for (j = 0;j < surface->num_vertices;j++)
10202                         {
10203                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10204                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10205                                 vi++;
10206                         }
10207                 }
10208                 R_Mesh_PrepareVertices_Generic_Unlock();
10209                 RSurf_DrawBatch();
10210         }
10211 }
10212
10213 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10214 {
10215         CHECKGLERROR
10216         RSurf_SetupDepthAndCulling();
10217         if (r_showsurfaces.integer)
10218         {
10219                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10220                 return;
10221         }
10222         switch (vid.renderpath)
10223         {
10224         case RENDERPATH_GL20:
10225         case RENDERPATH_D3D9:
10226         case RENDERPATH_D3D10:
10227         case RENDERPATH_D3D11:
10228         case RENDERPATH_SOFT:
10229         case RENDERPATH_GLES2:
10230                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10231                 break;
10232         case RENDERPATH_GL13:
10233         case RENDERPATH_GLES1:
10234                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10235                 break;
10236         case RENDERPATH_GL11:
10237                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10238                 break;
10239         }
10240         CHECKGLERROR
10241 }
10242
10243 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10244 {
10245         CHECKGLERROR
10246         RSurf_SetupDepthAndCulling();
10247         if (r_showsurfaces.integer)
10248         {
10249                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10250                 return;
10251         }
10252         switch (vid.renderpath)
10253         {
10254         case RENDERPATH_GL20:
10255         case RENDERPATH_D3D9:
10256         case RENDERPATH_D3D10:
10257         case RENDERPATH_D3D11:
10258         case RENDERPATH_SOFT:
10259         case RENDERPATH_GLES2:
10260                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10261                 break;
10262         case RENDERPATH_GL13:
10263         case RENDERPATH_GLES1:
10264                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10265                 break;
10266         case RENDERPATH_GL11:
10267                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10268                 break;
10269         }
10270         CHECKGLERROR
10271 }
10272
10273 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10274 {
10275         int i, j;
10276         int texturenumsurfaces, endsurface;
10277         texture_t *texture;
10278         const msurface_t *surface;
10279         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10280
10281         // if the model is static it doesn't matter what value we give for
10282         // wantnormals and wanttangents, so this logic uses only rules applicable
10283         // to a model, knowing that they are meaningless otherwise
10284         if (ent == r_refdef.scene.worldentity)
10285                 RSurf_ActiveWorldEntity();
10286         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10287                 RSurf_ActiveModelEntity(ent, false, false, false);
10288         else
10289         {
10290                 switch (vid.renderpath)
10291                 {
10292                 case RENDERPATH_GL20:
10293                 case RENDERPATH_D3D9:
10294                 case RENDERPATH_D3D10:
10295                 case RENDERPATH_D3D11:
10296                 case RENDERPATH_SOFT:
10297                 case RENDERPATH_GLES2:
10298                         RSurf_ActiveModelEntity(ent, true, true, false);
10299                         break;
10300                 case RENDERPATH_GL11:
10301                 case RENDERPATH_GL13:
10302                 case RENDERPATH_GLES1:
10303                         RSurf_ActiveModelEntity(ent, true, false, false);
10304                         break;
10305                 }
10306         }
10307
10308         if (r_transparentdepthmasking.integer)
10309         {
10310                 qboolean setup = false;
10311                 for (i = 0;i < numsurfaces;i = j)
10312                 {
10313                         j = i + 1;
10314                         surface = rsurface.modelsurfaces + surfacelist[i];
10315                         texture = surface->texture;
10316                         rsurface.texture = R_GetCurrentTexture(texture);
10317                         rsurface.lightmaptexture = NULL;
10318                         rsurface.deluxemaptexture = NULL;
10319                         rsurface.uselightmaptexture = false;
10320                         // scan ahead until we find a different texture
10321                         endsurface = min(i + 1024, numsurfaces);
10322                         texturenumsurfaces = 0;
10323                         texturesurfacelist[texturenumsurfaces++] = surface;
10324                         for (;j < endsurface;j++)
10325                         {
10326                                 surface = rsurface.modelsurfaces + surfacelist[j];
10327                                 if (texture != surface->texture)
10328                                         break;
10329                                 texturesurfacelist[texturenumsurfaces++] = surface;
10330                         }
10331                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10332                                 continue;
10333                         // render the range of surfaces as depth
10334                         if (!setup)
10335                         {
10336                                 setup = true;
10337                                 GL_ColorMask(0,0,0,0);
10338                                 GL_Color(1,1,1,1);
10339                                 GL_DepthTest(true);
10340                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10341                                 GL_DepthMask(true);
10342 //                              R_Mesh_ResetTextureState();
10343                                 R_SetupShader_DepthOrShadow(false);
10344                         }
10345                         RSurf_SetupDepthAndCulling();
10346                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10347                         if (rsurface.batchvertex3fbuffer)
10348                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10349                         else
10350                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10351                         RSurf_DrawBatch();
10352                 }
10353                 if (setup)
10354                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10355         }
10356
10357         for (i = 0;i < numsurfaces;i = j)
10358         {
10359                 j = i + 1;
10360                 surface = rsurface.modelsurfaces + surfacelist[i];
10361                 texture = surface->texture;
10362                 rsurface.texture = R_GetCurrentTexture(texture);
10363                 // scan ahead until we find a different texture
10364                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10365                 texturenumsurfaces = 0;
10366                 texturesurfacelist[texturenumsurfaces++] = surface;
10367                 if(FAKELIGHT_ENABLED)
10368                 {
10369                         rsurface.lightmaptexture = NULL;
10370                         rsurface.deluxemaptexture = NULL;
10371                         rsurface.uselightmaptexture = false;
10372                         for (;j < endsurface;j++)
10373                         {
10374                                 surface = rsurface.modelsurfaces + surfacelist[j];
10375                                 if (texture != surface->texture)
10376                                         break;
10377                                 texturesurfacelist[texturenumsurfaces++] = surface;
10378                         }
10379                 }
10380                 else
10381                 {
10382                         rsurface.lightmaptexture = surface->lightmaptexture;
10383                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10384                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10385                         for (;j < endsurface;j++)
10386                         {
10387                                 surface = rsurface.modelsurfaces + surfacelist[j];
10388                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10389                                         break;
10390                                 texturesurfacelist[texturenumsurfaces++] = surface;
10391                         }
10392                 }
10393                 // render the range of surfaces
10394                 if (ent == r_refdef.scene.worldentity)
10395                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10396                 else
10397                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10398         }
10399         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10400 }
10401
10402 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10403 {
10404         // transparent surfaces get pushed off into the transparent queue
10405         int surfacelistindex;
10406         const msurface_t *surface;
10407         vec3_t tempcenter, center;
10408         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10409         {
10410                 surface = texturesurfacelist[surfacelistindex];
10411                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10412                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10413                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10414                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10415                 if (queueentity->transparent_offset) // transparent offset
10416                 {
10417                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10418                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10419                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10420                 }
10421                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10422         }
10423 }
10424
10425 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10426 {
10427         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10428                 return;
10429         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10430                 return;
10431         RSurf_SetupDepthAndCulling();
10432         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10433         if (rsurface.batchvertex3fbuffer)
10434                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10435         else
10436                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10437         RSurf_DrawBatch();
10438 }
10439
10440 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10441 {
10442         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10443         CHECKGLERROR
10444         if (depthonly)
10445                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10446         else if (prepass)
10447         {
10448                 if (!rsurface.texture->currentnumlayers)
10449                         return;
10450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10451                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10452                 else
10453                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10454         }
10455         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10456                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10457         else if (!rsurface.texture->currentnumlayers)
10458                 return;
10459         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10460         {
10461                 // in the deferred case, transparent surfaces were queued during prepass
10462                 if (!r_shadow_usingdeferredprepass)
10463                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10464         }
10465         else
10466         {
10467                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10468                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10469         }
10470         CHECKGLERROR
10471 }
10472
10473 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10474 {
10475         int i, j;
10476         texture_t *texture;
10477         R_FrameData_SetMark();
10478         // break the surface list down into batches by texture and use of lightmapping
10479         for (i = 0;i < numsurfaces;i = j)
10480         {
10481                 j = i + 1;
10482                 // texture is the base texture pointer, rsurface.texture is the
10483                 // current frame/skin the texture is directing us to use (for example
10484                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10485                 // use skin 1 instead)
10486                 texture = surfacelist[i]->texture;
10487                 rsurface.texture = R_GetCurrentTexture(texture);
10488                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10489                 {
10490                         // if this texture is not the kind we want, skip ahead to the next one
10491                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10492                                 ;
10493                         continue;
10494                 }
10495                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10496                 {
10497                         rsurface.lightmaptexture = NULL;
10498                         rsurface.deluxemaptexture = NULL;
10499                         rsurface.uselightmaptexture = false;
10500                         // simply scan ahead until we find a different texture or lightmap state
10501                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10502                                 ;
10503                 }
10504                 else
10505                 {
10506                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10507                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10508                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10509                         // simply scan ahead until we find a different texture or lightmap state
10510                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10511                                 ;
10512                 }
10513                 // render the range of surfaces
10514                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10515         }
10516         R_FrameData_ReturnToMark();
10517 }
10518
10519 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10520 {
10521         CHECKGLERROR
10522         if (depthonly)
10523                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10524         else if (prepass)
10525         {
10526                 if (!rsurface.texture->currentnumlayers)
10527                         return;
10528                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10529                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10530                 else
10531                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10532         }
10533         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10534                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10535         else if (!rsurface.texture->currentnumlayers)
10536                 return;
10537         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10538         {
10539                 // in the deferred case, transparent surfaces were queued during prepass
10540                 if (!r_shadow_usingdeferredprepass)
10541                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10542         }
10543         else
10544         {
10545                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10546                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10547         }
10548         CHECKGLERROR
10549 }
10550
10551 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10552 {
10553         int i, j;
10554         texture_t *texture;
10555         R_FrameData_SetMark();
10556         // break the surface list down into batches by texture and use of lightmapping
10557         for (i = 0;i < numsurfaces;i = j)
10558         {
10559                 j = i + 1;
10560                 // texture is the base texture pointer, rsurface.texture is the
10561                 // current frame/skin the texture is directing us to use (for example
10562                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10563                 // use skin 1 instead)
10564                 texture = surfacelist[i]->texture;
10565                 rsurface.texture = R_GetCurrentTexture(texture);
10566                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10567                 {
10568                         // if this texture is not the kind we want, skip ahead to the next one
10569                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10570                                 ;
10571                         continue;
10572                 }
10573                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10574                 {
10575                         rsurface.lightmaptexture = NULL;
10576                         rsurface.deluxemaptexture = NULL;
10577                         rsurface.uselightmaptexture = false;
10578                         // simply scan ahead until we find a different texture or lightmap state
10579                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10580                                 ;
10581                 }
10582                 else
10583                 {
10584                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10585                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10586                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10587                         // simply scan ahead until we find a different texture or lightmap state
10588                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10589                                 ;
10590                 }
10591                 // render the range of surfaces
10592                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10593         }
10594         R_FrameData_ReturnToMark();
10595 }
10596
10597 float locboxvertex3f[6*4*3] =
10598 {
10599         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10600         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10601         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10602         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10603         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10604         1,0,0, 0,0,0, 0,1,0, 1,1,0
10605 };
10606
10607 unsigned short locboxelements[6*2*3] =
10608 {
10609          0, 1, 2, 0, 2, 3,
10610          4, 5, 6, 4, 6, 7,
10611          8, 9,10, 8,10,11,
10612         12,13,14, 12,14,15,
10613         16,17,18, 16,18,19,
10614         20,21,22, 20,22,23
10615 };
10616
10617 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10618 {
10619         int i, j;
10620         cl_locnode_t *loc = (cl_locnode_t *)ent;
10621         vec3_t mins, size;
10622         float vertex3f[6*4*3];
10623         CHECKGLERROR
10624         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10625         GL_DepthMask(false);
10626         GL_DepthRange(0, 1);
10627         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10628         GL_DepthTest(true);
10629         GL_CullFace(GL_NONE);
10630         R_EntityMatrix(&identitymatrix);
10631
10632 //      R_Mesh_ResetTextureState();
10633
10634         i = surfacelist[0];
10635         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10636                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10637                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10638                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10639
10640         if (VectorCompare(loc->mins, loc->maxs))
10641         {
10642                 VectorSet(size, 2, 2, 2);
10643                 VectorMA(loc->mins, -0.5f, size, mins);
10644         }
10645         else
10646         {
10647                 VectorCopy(loc->mins, mins);
10648                 VectorSubtract(loc->maxs, loc->mins, size);
10649         }
10650
10651         for (i = 0;i < 6*4*3;)
10652                 for (j = 0;j < 3;j++, i++)
10653                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10654
10655         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10656         R_SetupShader_Generic_NoTexture(false, false);
10657         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10658 }
10659
10660 void R_DrawLocs(void)
10661 {
10662         int index;
10663         cl_locnode_t *loc, *nearestloc;
10664         vec3_t center;
10665         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10666         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10667         {
10668                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10669                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10670         }
10671 }
10672
10673 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10674 {
10675         if (decalsystem->decals)
10676                 Mem_Free(decalsystem->decals);
10677         memset(decalsystem, 0, sizeof(*decalsystem));
10678 }
10679
10680 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)
10681 {
10682         tridecal_t *decal;
10683         tridecal_t *decals;
10684         int i;
10685
10686         // expand or initialize the system
10687         if (decalsystem->maxdecals <= decalsystem->numdecals)
10688         {
10689                 decalsystem_t old = *decalsystem;
10690                 qboolean useshortelements;
10691                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10692                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10693                 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)));
10694                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10695                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10696                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10697                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10698                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10699                 if (decalsystem->numdecals)
10700                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10701                 if (old.decals)
10702                         Mem_Free(old.decals);
10703                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10704                         decalsystem->element3i[i] = i;
10705                 if (useshortelements)
10706                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10707                                 decalsystem->element3s[i] = i;
10708         }
10709
10710         // grab a decal and search for another free slot for the next one
10711         decals = decalsystem->decals;
10712         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10713         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10714                 ;
10715         decalsystem->freedecal = i;
10716         if (decalsystem->numdecals <= i)
10717                 decalsystem->numdecals = i + 1;
10718
10719         // initialize the decal
10720         decal->lived = 0;
10721         decal->triangleindex = triangleindex;
10722         decal->surfaceindex = surfaceindex;
10723         decal->decalsequence = decalsequence;
10724         decal->color4f[0][0] = c0[0];
10725         decal->color4f[0][1] = c0[1];
10726         decal->color4f[0][2] = c0[2];
10727         decal->color4f[0][3] = 1;
10728         decal->color4f[1][0] = c1[0];
10729         decal->color4f[1][1] = c1[1];
10730         decal->color4f[1][2] = c1[2];
10731         decal->color4f[1][3] = 1;
10732         decal->color4f[2][0] = c2[0];
10733         decal->color4f[2][1] = c2[1];
10734         decal->color4f[2][2] = c2[2];
10735         decal->color4f[2][3] = 1;
10736         decal->vertex3f[0][0] = v0[0];
10737         decal->vertex3f[0][1] = v0[1];
10738         decal->vertex3f[0][2] = v0[2];
10739         decal->vertex3f[1][0] = v1[0];
10740         decal->vertex3f[1][1] = v1[1];
10741         decal->vertex3f[1][2] = v1[2];
10742         decal->vertex3f[2][0] = v2[0];
10743         decal->vertex3f[2][1] = v2[1];
10744         decal->vertex3f[2][2] = v2[2];
10745         decal->texcoord2f[0][0] = t0[0];
10746         decal->texcoord2f[0][1] = t0[1];
10747         decal->texcoord2f[1][0] = t1[0];
10748         decal->texcoord2f[1][1] = t1[1];
10749         decal->texcoord2f[2][0] = t2[0];
10750         decal->texcoord2f[2][1] = t2[1];
10751         TriangleNormal(v0, v1, v2, decal->plane);
10752         VectorNormalize(decal->plane);
10753         decal->plane[3] = DotProduct(v0, decal->plane);
10754 }
10755
10756 extern cvar_t cl_decals_bias;
10757 extern cvar_t cl_decals_models;
10758 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10759 // baseparms, parms, temps
10760 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)
10761 {
10762         int cornerindex;
10763         int index;
10764         float v[9][3];
10765         const float *vertex3f;
10766         const float *normal3f;
10767         int numpoints;
10768         float points[2][9][3];
10769         float temp[3];
10770         float tc[9][2];
10771         float f;
10772         float c[9][4];
10773         const int *e;
10774
10775         e = rsurface.modelelement3i + 3*triangleindex;
10776
10777         vertex3f = rsurface.modelvertex3f;
10778         normal3f = rsurface.modelnormal3f;
10779
10780         if (normal3f)
10781         {
10782                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10783                 {
10784                         index = 3*e[cornerindex];
10785                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10786                 }
10787         }
10788         else
10789         {
10790                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10791                 {
10792                         index = 3*e[cornerindex];
10793                         VectorCopy(vertex3f + index, v[cornerindex]);
10794                 }
10795         }
10796
10797         // cull backfaces
10798         //TriangleNormal(v[0], v[1], v[2], normal);
10799         //if (DotProduct(normal, localnormal) < 0.0f)
10800         //      continue;
10801         // clip by each of the box planes formed from the projection matrix
10802         // if anything survives, we emit the decal
10803         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]);
10804         if (numpoints < 3)
10805                 return;
10806         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]);
10807         if (numpoints < 3)
10808                 return;
10809         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]);
10810         if (numpoints < 3)
10811                 return;
10812         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]);
10813         if (numpoints < 3)
10814                 return;
10815         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]);
10816         if (numpoints < 3)
10817                 return;
10818         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]);
10819         if (numpoints < 3)
10820                 return;
10821         // some part of the triangle survived, so we have to accept it...
10822         if (dynamic)
10823         {
10824                 // dynamic always uses the original triangle
10825                 numpoints = 3;
10826                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10827                 {
10828                         index = 3*e[cornerindex];
10829                         VectorCopy(vertex3f + index, v[cornerindex]);
10830                 }
10831         }
10832         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10833         {
10834                 // convert vertex positions to texcoords
10835                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10836                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10837                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10838                 // calculate distance fade from the projection origin
10839                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10840                 f = bound(0.0f, f, 1.0f);
10841                 c[cornerindex][0] = r * f;
10842                 c[cornerindex][1] = g * f;
10843                 c[cornerindex][2] = b * f;
10844                 c[cornerindex][3] = 1.0f;
10845                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10846         }
10847         if (dynamic)
10848                 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);
10849         else
10850                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10851                         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);
10852 }
10853 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)
10854 {
10855         matrix4x4_t projection;
10856         decalsystem_t *decalsystem;
10857         qboolean dynamic;
10858         dp_model_t *model;
10859         const msurface_t *surface;
10860         const msurface_t *surfaces;
10861         const int *surfacelist;
10862         const texture_t *texture;
10863         int numtriangles;
10864         int numsurfacelist;
10865         int surfacelistindex;
10866         int surfaceindex;
10867         int triangleindex;
10868         float localorigin[3];
10869         float localnormal[3];
10870         float localmins[3];
10871         float localmaxs[3];
10872         float localsize;
10873         //float normal[3];
10874         float planes[6][4];
10875         float angles[3];
10876         bih_t *bih;
10877         int bih_triangles_count;
10878         int bih_triangles[256];
10879         int bih_surfaces[256];
10880
10881         decalsystem = &ent->decalsystem;
10882         model = ent->model;
10883         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10884         {
10885                 R_DecalSystem_Reset(&ent->decalsystem);
10886                 return;
10887         }
10888
10889         if (!model->brush.data_leafs && !cl_decals_models.integer)
10890         {
10891                 if (decalsystem->model)
10892                         R_DecalSystem_Reset(decalsystem);
10893                 return;
10894         }
10895
10896         if (decalsystem->model != model)
10897                 R_DecalSystem_Reset(decalsystem);
10898         decalsystem->model = model;
10899
10900         RSurf_ActiveModelEntity(ent, true, false, false);
10901
10902         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10903         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10904         VectorNormalize(localnormal);
10905         localsize = worldsize*rsurface.inversematrixscale;
10906         localmins[0] = localorigin[0] - localsize;
10907         localmins[1] = localorigin[1] - localsize;
10908         localmins[2] = localorigin[2] - localsize;
10909         localmaxs[0] = localorigin[0] + localsize;
10910         localmaxs[1] = localorigin[1] + localsize;
10911         localmaxs[2] = localorigin[2] + localsize;
10912
10913         //VectorCopy(localnormal, planes[4]);
10914         //VectorVectors(planes[4], planes[2], planes[0]);
10915         AnglesFromVectors(angles, localnormal, NULL, false);
10916         AngleVectors(angles, planes[0], planes[2], planes[4]);
10917         VectorNegate(planes[0], planes[1]);
10918         VectorNegate(planes[2], planes[3]);
10919         VectorNegate(planes[4], planes[5]);
10920         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10921         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10922         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10923         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10924         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10925         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10926
10927 #if 1
10928 // works
10929 {
10930         matrix4x4_t forwardprojection;
10931         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10932         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10933 }
10934 #else
10935 // broken
10936 {
10937         float projectionvector[4][3];
10938         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10939         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10940         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10941         projectionvector[0][0] = planes[0][0] * ilocalsize;
10942         projectionvector[0][1] = planes[1][0] * ilocalsize;
10943         projectionvector[0][2] = planes[2][0] * ilocalsize;
10944         projectionvector[1][0] = planes[0][1] * ilocalsize;
10945         projectionvector[1][1] = planes[1][1] * ilocalsize;
10946         projectionvector[1][2] = planes[2][1] * ilocalsize;
10947         projectionvector[2][0] = planes[0][2] * ilocalsize;
10948         projectionvector[2][1] = planes[1][2] * ilocalsize;
10949         projectionvector[2][2] = planes[2][2] * ilocalsize;
10950         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10951         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10952         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10953         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10954 }
10955 #endif
10956
10957         dynamic = model->surfmesh.isanimated;
10958         numsurfacelist = model->nummodelsurfaces;
10959         surfacelist = model->sortedmodelsurfaces;
10960         surfaces = model->data_surfaces;
10961
10962         bih = NULL;
10963         bih_triangles_count = -1;
10964         if(!dynamic)
10965         {
10966                 if(model->render_bih.numleafs)
10967                         bih = &model->render_bih;
10968                 else if(model->collision_bih.numleafs)
10969                         bih = &model->collision_bih;
10970         }
10971         if(bih)
10972                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10973         if(bih_triangles_count == 0)
10974                 return;
10975         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10976                 return;
10977         if(bih_triangles_count > 0)
10978         {
10979                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10980                 {
10981                         surfaceindex = bih_surfaces[triangleindex];
10982                         surface = surfaces + surfaceindex;
10983                         texture = surface->texture;
10984                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10985                                 continue;
10986                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10987                                 continue;
10988                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10989                 }
10990         }
10991         else
10992         {
10993                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10994                 {
10995                         surfaceindex = surfacelist[surfacelistindex];
10996                         surface = surfaces + surfaceindex;
10997                         // check cull box first because it rejects more than any other check
10998                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10999                                 continue;
11000                         // skip transparent surfaces
11001                         texture = surface->texture;
11002                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11003                                 continue;
11004                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11005                                 continue;
11006                         numtriangles = surface->num_triangles;
11007                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11008                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11009                 }
11010         }
11011 }
11012
11013 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11014 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)
11015 {
11016         int renderentityindex;
11017         float worldmins[3];
11018         float worldmaxs[3];
11019         entity_render_t *ent;
11020
11021         if (!cl_decals_newsystem.integer)
11022                 return;
11023
11024         worldmins[0] = worldorigin[0] - worldsize;
11025         worldmins[1] = worldorigin[1] - worldsize;
11026         worldmins[2] = worldorigin[2] - worldsize;
11027         worldmaxs[0] = worldorigin[0] + worldsize;
11028         worldmaxs[1] = worldorigin[1] + worldsize;
11029         worldmaxs[2] = worldorigin[2] + worldsize;
11030
11031         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11032
11033         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11034         {
11035                 ent = r_refdef.scene.entities[renderentityindex];
11036                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11037                         continue;
11038
11039                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11040         }
11041 }
11042
11043 typedef struct r_decalsystem_splatqueue_s
11044 {
11045         vec3_t worldorigin;
11046         vec3_t worldnormal;
11047         float color[4];
11048         float tcrange[4];
11049         float worldsize;
11050         int decalsequence;
11051 }
11052 r_decalsystem_splatqueue_t;
11053
11054 int r_decalsystem_numqueued = 0;
11055 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11056
11057 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)
11058 {
11059         r_decalsystem_splatqueue_t *queue;
11060
11061         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11062                 return;
11063
11064         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11065         VectorCopy(worldorigin, queue->worldorigin);
11066         VectorCopy(worldnormal, queue->worldnormal);
11067         Vector4Set(queue->color, r, g, b, a);
11068         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11069         queue->worldsize = worldsize;
11070         queue->decalsequence = cl.decalsequence++;
11071 }
11072
11073 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11074 {
11075         int i;
11076         r_decalsystem_splatqueue_t *queue;
11077
11078         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11079                 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);
11080         r_decalsystem_numqueued = 0;
11081 }
11082
11083 extern cvar_t cl_decals_max;
11084 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11085 {
11086         int i;
11087         decalsystem_t *decalsystem = &ent->decalsystem;
11088         int numdecals;
11089         int killsequence;
11090         tridecal_t *decal;
11091         float frametime;
11092         float lifetime;
11093
11094         if (!decalsystem->numdecals)
11095                 return;
11096
11097         if (r_showsurfaces.integer)
11098                 return;
11099
11100         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11101         {
11102                 R_DecalSystem_Reset(decalsystem);
11103                 return;
11104         }
11105
11106         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11107         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11108
11109         if (decalsystem->lastupdatetime)
11110                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11111         else
11112                 frametime = 0;
11113         decalsystem->lastupdatetime = r_refdef.scene.time;
11114         decal = decalsystem->decals;
11115         numdecals = decalsystem->numdecals;
11116
11117         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11118         {
11119                 if (decal->color4f[0][3])
11120                 {
11121                         decal->lived += frametime;
11122                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11123                         {
11124                                 memset(decal, 0, sizeof(*decal));
11125                                 if (decalsystem->freedecal > i)
11126                                         decalsystem->freedecal = i;
11127                         }
11128                 }
11129         }
11130         decal = decalsystem->decals;
11131         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11132                 numdecals--;
11133
11134         // collapse the array by shuffling the tail decals into the gaps
11135         for (;;)
11136         {
11137                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11138                         decalsystem->freedecal++;
11139                 if (decalsystem->freedecal == numdecals)
11140                         break;
11141                 decal[decalsystem->freedecal] = decal[--numdecals];
11142         }
11143
11144         decalsystem->numdecals = numdecals;
11145
11146         if (numdecals <= 0)
11147         {
11148                 // if there are no decals left, reset decalsystem
11149                 R_DecalSystem_Reset(decalsystem);
11150         }
11151 }
11152
11153 extern skinframe_t *decalskinframe;
11154 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11155 {
11156         int i;
11157         decalsystem_t *decalsystem = &ent->decalsystem;
11158         int numdecals;
11159         tridecal_t *decal;
11160         float faderate;
11161         float alpha;
11162         float *v3f;
11163         float *c4f;
11164         float *t2f;
11165         const int *e;
11166         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11167         int numtris = 0;
11168
11169         numdecals = decalsystem->numdecals;
11170         if (!numdecals)
11171                 return;
11172
11173         if (r_showsurfaces.integer)
11174                 return;
11175
11176         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11177         {
11178                 R_DecalSystem_Reset(decalsystem);
11179                 return;
11180         }
11181
11182         // if the model is static it doesn't matter what value we give for
11183         // wantnormals and wanttangents, so this logic uses only rules applicable
11184         // to a model, knowing that they are meaningless otherwise
11185         if (ent == r_refdef.scene.worldentity)
11186                 RSurf_ActiveWorldEntity();
11187         else
11188                 RSurf_ActiveModelEntity(ent, false, false, false);
11189
11190         decalsystem->lastupdatetime = r_refdef.scene.time;
11191         decal = decalsystem->decals;
11192
11193         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11194
11195         // update vertex positions for animated models
11196         v3f = decalsystem->vertex3f;
11197         c4f = decalsystem->color4f;
11198         t2f = decalsystem->texcoord2f;
11199         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11200         {
11201                 if (!decal->color4f[0][3])
11202                         continue;
11203
11204                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11205                         continue;
11206
11207                 // skip backfaces
11208                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11209                         continue;
11210
11211                 // update color values for fading decals
11212                 if (decal->lived >= cl_decals_time.value)
11213                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11214                 else
11215                         alpha = 1.0f;
11216
11217                 c4f[ 0] = decal->color4f[0][0] * alpha;
11218                 c4f[ 1] = decal->color4f[0][1] * alpha;
11219                 c4f[ 2] = decal->color4f[0][2] * alpha;
11220                 c4f[ 3] = 1;
11221                 c4f[ 4] = decal->color4f[1][0] * alpha;
11222                 c4f[ 5] = decal->color4f[1][1] * alpha;
11223                 c4f[ 6] = decal->color4f[1][2] * alpha;
11224                 c4f[ 7] = 1;
11225                 c4f[ 8] = decal->color4f[2][0] * alpha;
11226                 c4f[ 9] = decal->color4f[2][1] * alpha;
11227                 c4f[10] = decal->color4f[2][2] * alpha;
11228                 c4f[11] = 1;
11229
11230                 t2f[0] = decal->texcoord2f[0][0];
11231                 t2f[1] = decal->texcoord2f[0][1];
11232                 t2f[2] = decal->texcoord2f[1][0];
11233                 t2f[3] = decal->texcoord2f[1][1];
11234                 t2f[4] = decal->texcoord2f[2][0];
11235                 t2f[5] = decal->texcoord2f[2][1];
11236
11237                 // update vertex positions for animated models
11238                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11239                 {
11240                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11241                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11242                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11243                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11244                 }
11245                 else
11246                 {
11247                         VectorCopy(decal->vertex3f[0], v3f);
11248                         VectorCopy(decal->vertex3f[1], v3f + 3);
11249                         VectorCopy(decal->vertex3f[2], v3f + 6);
11250                 }
11251
11252                 if (r_refdef.fogenabled)
11253                 {
11254                         alpha = RSurf_FogVertex(v3f);
11255                         VectorScale(c4f, alpha, c4f);
11256                         alpha = RSurf_FogVertex(v3f + 3);
11257                         VectorScale(c4f + 4, alpha, c4f + 4);
11258                         alpha = RSurf_FogVertex(v3f + 6);
11259                         VectorScale(c4f + 8, alpha, c4f + 8);
11260                 }
11261
11262                 v3f += 9;
11263                 c4f += 12;
11264                 t2f += 6;
11265                 numtris++;
11266         }
11267
11268         if (numtris > 0)
11269         {
11270                 r_refdef.stats.drawndecals += numtris;
11271
11272                 // now render the decals all at once
11273                 // (this assumes they all use one particle font texture!)
11274                 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);
11275 //              R_Mesh_ResetTextureState();
11276                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11277                 GL_DepthMask(false);
11278                 GL_DepthRange(0, 1);
11279                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11280                 GL_DepthTest(true);
11281                 GL_CullFace(GL_NONE);
11282                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11283                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11284                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11285         }
11286 }
11287
11288 static void R_DrawModelDecals(void)
11289 {
11290         int i, numdecals;
11291
11292         // fade faster when there are too many decals
11293         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11294         for (i = 0;i < r_refdef.scene.numentities;i++)
11295                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11296
11297         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11298         for (i = 0;i < r_refdef.scene.numentities;i++)
11299                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11300                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11301
11302         R_DecalSystem_ApplySplatEntitiesQueue();
11303
11304         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11305         for (i = 0;i < r_refdef.scene.numentities;i++)
11306                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11307
11308         r_refdef.stats.totaldecals += numdecals;
11309
11310         if (r_showsurfaces.integer)
11311                 return;
11312
11313         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11314
11315         for (i = 0;i < r_refdef.scene.numentities;i++)
11316         {
11317                 if (!r_refdef.viewcache.entityvisible[i])
11318                         continue;
11319                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11320                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11321         }
11322 }
11323
11324 extern cvar_t mod_collision_bih;
11325 static void R_DrawDebugModel(void)
11326 {
11327         entity_render_t *ent = rsurface.entity;
11328         int i, j, k, l, flagsmask;
11329         const msurface_t *surface;
11330         dp_model_t *model = ent->model;
11331         vec3_t v;
11332
11333         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11334                 return;
11335
11336         if (r_showoverdraw.value > 0)
11337         {
11338                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11339                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11340                 R_SetupShader_Generic_NoTexture(false, false);
11341                 GL_DepthTest(false);
11342                 GL_DepthMask(false);
11343                 GL_DepthRange(0, 1);
11344                 GL_BlendFunc(GL_ONE, GL_ONE);
11345                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11346                 {
11347                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11348                                 continue;
11349                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11350                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11351                         {
11352                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11353                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11354                                 if (!rsurface.texture->currentlayers->depthmask)
11355                                         GL_Color(c, 0, 0, 1.0f);
11356                                 else if (ent == r_refdef.scene.worldentity)
11357                                         GL_Color(c, c, c, 1.0f);
11358                                 else
11359                                         GL_Color(0, c, 0, 1.0f);
11360                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11361                                 RSurf_DrawBatch();
11362                         }
11363                 }
11364                 rsurface.texture = NULL;
11365         }
11366
11367         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11368
11369 //      R_Mesh_ResetTextureState();
11370         R_SetupShader_Generic_NoTexture(false, false);
11371         GL_DepthRange(0, 1);
11372         GL_DepthTest(!r_showdisabledepthtest.integer);
11373         GL_DepthMask(false);
11374         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11375
11376         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11377         {
11378                 int triangleindex;
11379                 int bihleafindex;
11380                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11381                 const q3mbrush_t *brush;
11382                 const bih_t *bih = &model->collision_bih;
11383                 const bih_leaf_t *bihleaf;
11384                 float vertex3f[3][3];
11385                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11386                 cullbox = false;
11387                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11388                 {
11389                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11390                                 continue;
11391                         switch (bihleaf->type)
11392                         {
11393                         case BIH_BRUSH:
11394                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11395                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11396                                 {
11397                                         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);
11398                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11399                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11400                                 }
11401                                 break;
11402                         case BIH_COLLISIONTRIANGLE:
11403                                 triangleindex = bihleaf->itemindex;
11404                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11405                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11406                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11407                                 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);
11408                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11409                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11410                                 break;
11411                         case BIH_RENDERTRIANGLE:
11412                                 triangleindex = bihleaf->itemindex;
11413                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11414                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11415                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11416                                 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);
11417                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11418                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11419                                 break;
11420                         }
11421                 }
11422         }
11423
11424         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11425
11426 #ifndef USE_GLES2
11427         if (r_showtris.integer && qglPolygonMode)
11428         {
11429                 if (r_showdisabledepthtest.integer)
11430                 {
11431                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11432                         GL_DepthMask(false);
11433                 }
11434                 else
11435                 {
11436                         GL_BlendFunc(GL_ONE, GL_ZERO);
11437                         GL_DepthMask(true);
11438                 }
11439                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11440                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11441                 {
11442                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11443                                 continue;
11444                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11445                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11446                         {
11447                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11448                                 if (!rsurface.texture->currentlayers->depthmask)
11449                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11450                                 else if (ent == r_refdef.scene.worldentity)
11451                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11452                                 else
11453                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11454                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11455                                 RSurf_DrawBatch();
11456                         }
11457                 }
11458                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11459                 rsurface.texture = NULL;
11460         }
11461
11462         if (r_shownormals.value != 0 && qglBegin)
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                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11475                 {
11476                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11477                                 continue;
11478                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11479                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11480                         {
11481                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11482                                 qglBegin(GL_LINES);
11483                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11484                                 {
11485                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11486                                         {
11487                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11488                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11489                                                 qglVertex3f(v[0], v[1], v[2]);
11490                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11491                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11492                                                 qglVertex3f(v[0], v[1], v[2]);
11493                                         }
11494                                 }
11495                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11496                                 {
11497                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11498                                         {
11499                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11500                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11501                                                 qglVertex3f(v[0], v[1], v[2]);
11502                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11503                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11504                                                 qglVertex3f(v[0], v[1], v[2]);
11505                                         }
11506                                 }
11507                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11508                                 {
11509                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11510                                         {
11511                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11512                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11513                                                 qglVertex3f(v[0], v[1], v[2]);
11514                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11515                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11516                                                 qglVertex3f(v[0], v[1], v[2]);
11517                                         }
11518                                 }
11519                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11520                                 {
11521                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11522                                         {
11523                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11524                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11525                                                 qglVertex3f(v[0], v[1], v[2]);
11526                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11527                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11528                                                 qglVertex3f(v[0], v[1], v[2]);
11529                                         }
11530                                 }
11531                                 qglEnd();
11532                                 CHECKGLERROR
11533                         }
11534                 }
11535                 rsurface.texture = NULL;
11536         }
11537 #endif
11538 }
11539
11540 int r_maxsurfacelist = 0;
11541 const msurface_t **r_surfacelist = NULL;
11542 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11543 {
11544         int i, j, endj, flagsmask;
11545         dp_model_t *model = r_refdef.scene.worldmodel;
11546         msurface_t *surfaces;
11547         unsigned char *update;
11548         int numsurfacelist = 0;
11549         if (model == NULL)
11550                 return;
11551
11552         if (r_maxsurfacelist < model->num_surfaces)
11553         {
11554                 r_maxsurfacelist = model->num_surfaces;
11555                 if (r_surfacelist)
11556                         Mem_Free((msurface_t**)r_surfacelist);
11557                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11558         }
11559
11560         RSurf_ActiveWorldEntity();
11561
11562         surfaces = model->data_surfaces;
11563         update = model->brushq1.lightmapupdateflags;
11564
11565         // update light styles on this submodel
11566         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11567         {
11568                 model_brush_lightstyleinfo_t *style;
11569                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11570                 {
11571                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11572                         {
11573                                 int *list = style->surfacelist;
11574                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11575                                 for (j = 0;j < style->numsurfaces;j++)
11576                                         update[list[j]] = true;
11577                         }
11578                 }
11579         }
11580
11581         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11582
11583         if (debug)
11584         {
11585                 R_DrawDebugModel();
11586                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11587                 return;
11588         }
11589
11590         rsurface.lightmaptexture = NULL;
11591         rsurface.deluxemaptexture = NULL;
11592         rsurface.uselightmaptexture = false;
11593         rsurface.texture = NULL;
11594         rsurface.rtlight = NULL;
11595         numsurfacelist = 0;
11596         // add visible surfaces to draw list
11597         for (i = 0;i < model->nummodelsurfaces;i++)
11598         {
11599                 j = model->sortedmodelsurfaces[i];
11600                 if (r_refdef.viewcache.world_surfacevisible[j])
11601                         r_surfacelist[numsurfacelist++] = surfaces + j;
11602         }
11603         // update lightmaps if needed
11604         if (model->brushq1.firstrender)
11605         {
11606                 model->brushq1.firstrender = false;
11607                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11608                         if (update[j])
11609                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11610         }
11611         else if (update)
11612         {
11613                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11614                         if (r_refdef.viewcache.world_surfacevisible[j])
11615                                 if (update[j])
11616                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11617         }
11618         // don't do anything if there were no surfaces
11619         if (!numsurfacelist)
11620         {
11621                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11622                 return;
11623         }
11624         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11625
11626         // add to stats if desired
11627         if (r_speeds.integer && !skysurfaces && !depthonly)
11628         {
11629                 r_refdef.stats.world_surfaces += numsurfacelist;
11630                 for (j = 0;j < numsurfacelist;j++)
11631                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11632         }
11633
11634         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11635 }
11636
11637 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11638 {
11639         int i, j, endj, flagsmask;
11640         dp_model_t *model = ent->model;
11641         msurface_t *surfaces;
11642         unsigned char *update;
11643         int numsurfacelist = 0;
11644         if (model == NULL)
11645                 return;
11646
11647         if (r_maxsurfacelist < model->num_surfaces)
11648         {
11649                 r_maxsurfacelist = model->num_surfaces;
11650                 if (r_surfacelist)
11651                         Mem_Free((msurface_t **)r_surfacelist);
11652                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11653         }
11654
11655         // if the model is static it doesn't matter what value we give for
11656         // wantnormals and wanttangents, so this logic uses only rules applicable
11657         // to a model, knowing that they are meaningless otherwise
11658         if (ent == r_refdef.scene.worldentity)
11659                 RSurf_ActiveWorldEntity();
11660         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11661                 RSurf_ActiveModelEntity(ent, false, false, false);
11662         else if (prepass)
11663                 RSurf_ActiveModelEntity(ent, true, true, true);
11664         else if (depthonly)
11665         {
11666                 switch (vid.renderpath)
11667                 {
11668                 case RENDERPATH_GL20:
11669                 case RENDERPATH_D3D9:
11670                 case RENDERPATH_D3D10:
11671                 case RENDERPATH_D3D11:
11672                 case RENDERPATH_SOFT:
11673                 case RENDERPATH_GLES2:
11674                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11675                         break;
11676                 case RENDERPATH_GL11:
11677                 case RENDERPATH_GL13:
11678                 case RENDERPATH_GLES1:
11679                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11680                         break;
11681                 }
11682         }
11683         else
11684         {
11685                 switch (vid.renderpath)
11686                 {
11687                 case RENDERPATH_GL20:
11688                 case RENDERPATH_D3D9:
11689                 case RENDERPATH_D3D10:
11690                 case RENDERPATH_D3D11:
11691                 case RENDERPATH_SOFT:
11692                 case RENDERPATH_GLES2:
11693                         RSurf_ActiveModelEntity(ent, true, true, false);
11694                         break;
11695                 case RENDERPATH_GL11:
11696                 case RENDERPATH_GL13:
11697                 case RENDERPATH_GLES1:
11698                         RSurf_ActiveModelEntity(ent, true, false, false);
11699                         break;
11700                 }
11701         }
11702
11703         surfaces = model->data_surfaces;
11704         update = model->brushq1.lightmapupdateflags;
11705
11706         // update light styles
11707         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11708         {
11709                 model_brush_lightstyleinfo_t *style;
11710                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11711                 {
11712                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11713                         {
11714                                 int *list = style->surfacelist;
11715                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11716                                 for (j = 0;j < style->numsurfaces;j++)
11717                                         update[list[j]] = true;
11718                         }
11719                 }
11720         }
11721
11722         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11723
11724         if (debug)
11725         {
11726                 R_DrawDebugModel();
11727                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11728                 return;
11729         }
11730
11731         rsurface.lightmaptexture = NULL;
11732         rsurface.deluxemaptexture = NULL;
11733         rsurface.uselightmaptexture = false;
11734         rsurface.texture = NULL;
11735         rsurface.rtlight = NULL;
11736         numsurfacelist = 0;
11737         // add visible surfaces to draw list
11738         for (i = 0;i < model->nummodelsurfaces;i++)
11739                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11740         // don't do anything if there were no surfaces
11741         if (!numsurfacelist)
11742         {
11743                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11744                 return;
11745         }
11746         // update lightmaps if needed
11747         if (update)
11748         {
11749                 int updated = 0;
11750                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11751                 {
11752                         if (update[j])
11753                         {
11754                                 updated++;
11755                                 R_BuildLightMap(ent, surfaces + j);
11756                         }
11757                 }
11758         }
11759         if (update)
11760                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11761                         if (update[j])
11762                                 R_BuildLightMap(ent, surfaces + j);
11763         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11764
11765         // add to stats if desired
11766         if (r_speeds.integer && !skysurfaces && !depthonly)
11767         {
11768                 r_refdef.stats.entities_surfaces += numsurfacelist;
11769                 for (j = 0;j < numsurfacelist;j++)
11770                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11771         }
11772
11773         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11774 }
11775
11776 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11777 {
11778         static texture_t texture;
11779         static msurface_t surface;
11780         const msurface_t *surfacelist = &surface;
11781
11782         // fake enough texture and surface state to render this geometry
11783
11784         texture.update_lastrenderframe = -1; // regenerate this texture
11785         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11786         texture.currentskinframe = skinframe;
11787         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11788         texture.offsetmapping = OFFSETMAPPING_OFF;
11789         texture.offsetscale = 1;
11790         texture.specularscalemod = 1;
11791         texture.specularpowermod = 1;
11792
11793         surface.texture = &texture;
11794         surface.num_triangles = numtriangles;
11795         surface.num_firsttriangle = firsttriangle;
11796         surface.num_vertices = numvertices;
11797         surface.num_firstvertex = firstvertex;
11798
11799         // now render it
11800         rsurface.texture = R_GetCurrentTexture(surface.texture);
11801         rsurface.lightmaptexture = NULL;
11802         rsurface.deluxemaptexture = NULL;
11803         rsurface.uselightmaptexture = false;
11804         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11805 }
11806
11807 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)
11808 {
11809         static msurface_t surface;
11810         const msurface_t *surfacelist = &surface;
11811
11812         // fake enough texture and surface state to render this geometry
11813         surface.texture = texture;
11814         surface.num_triangles = numtriangles;
11815         surface.num_firsttriangle = firsttriangle;
11816         surface.num_vertices = numvertices;
11817         surface.num_firstvertex = firstvertex;
11818
11819         // now render it
11820         rsurface.texture = R_GetCurrentTexture(surface.texture);
11821         rsurface.lightmaptexture = NULL;
11822         rsurface.deluxemaptexture = NULL;
11823         rsurface.uselightmaptexture = false;
11824         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11825 }