]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
e9b213b7559d05e909059607ac9e5b0c2b700433
[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
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
190
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
198
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
211
212 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"};
213
214 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"};
215
216 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
217
218 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
219
220 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
221 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"};
222
223 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."};
224
225 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)"};
226
227 extern cvar_t v_glslgamma;
228 extern cvar_t v_glslgamma_2d;
229
230 extern qboolean v_flipped_state;
231
232 static struct r_bloomstate_s
233 {
234         qboolean enabled;
235         qboolean hdr;
236
237         int bloomwidth, bloomheight;
238
239         textype_t texturetype;
240         int viewfbo; // used to check if r_viewfbo cvar has changed
241
242         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
243         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
244         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
245
246         int screentexturewidth, screentextureheight;
247         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
248
249         int bloomtexturewidth, bloomtextureheight;
250         rtexture_t *texture_bloom;
251
252         // arrays for rendering the screen passes
253         float screentexcoord2f[8];
254         float bloomtexcoord2f[8];
255         float offsettexcoord2f[8];
256
257         r_viewport_t viewport;
258 }
259 r_bloomstate;
260
261 r_waterstate_t r_waterstate;
262
263 /// shadow volume bsp struct with automatically growing nodes buffer
264 svbsp_t r_svbsp;
265
266 rtexture_t *r_texture_blanknormalmap;
267 rtexture_t *r_texture_white;
268 rtexture_t *r_texture_grey128;
269 rtexture_t *r_texture_black;
270 rtexture_t *r_texture_notexture;
271 rtexture_t *r_texture_whitecube;
272 rtexture_t *r_texture_normalizationcube;
273 rtexture_t *r_texture_fogattenuation;
274 rtexture_t *r_texture_fogheighttexture;
275 rtexture_t *r_texture_gammaramps;
276 unsigned int r_texture_gammaramps_serial;
277 //rtexture_t *r_texture_fogintensity;
278 rtexture_t *r_texture_reflectcube;
279
280 // TODO: hash lookups?
281 typedef struct cubemapinfo_s
282 {
283         char basename[64];
284         rtexture_t *texture;
285 }
286 cubemapinfo_t;
287
288 int r_texture_numcubemaps;
289 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
290
291 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
292 unsigned int r_numqueries;
293 unsigned int r_maxqueries;
294
295 typedef struct r_qwskincache_s
296 {
297         char name[MAX_QPATH];
298         skinframe_t *skinframe;
299 }
300 r_qwskincache_t;
301
302 static r_qwskincache_t *r_qwskincache;
303 static int r_qwskincache_size;
304
305 /// vertex coordinates for a quad that covers the screen exactly
306 extern const float r_screenvertex3f[12];
307 extern const float r_d3dscreenvertex3f[12];
308 const float r_screenvertex3f[12] =
309 {
310         0, 0, 0,
311         1, 0, 0,
312         1, 1, 0,
313         0, 1, 0
314 };
315 const float r_d3dscreenvertex3f[12] =
316 {
317         0, 1, 0,
318         1, 1, 0,
319         1, 0, 0,
320         0, 0, 0
321 };
322
323 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
324 {
325         int i;
326         for (i = 0;i < verts;i++)
327         {
328                 out[0] = in[0] * r;
329                 out[1] = in[1] * g;
330                 out[2] = in[2] * b;
331                 out[3] = in[3];
332                 in += 4;
333                 out += 4;
334         }
335 }
336
337 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
338 {
339         int i;
340         for (i = 0;i < verts;i++)
341         {
342                 out[0] = r;
343                 out[1] = g;
344                 out[2] = b;
345                 out[3] = a;
346                 out += 4;
347         }
348 }
349
350 // FIXME: move this to client?
351 void FOG_clear(void)
352 {
353         if (gamemode == GAME_NEHAHRA)
354         {
355                 Cvar_Set("gl_fogenable", "0");
356                 Cvar_Set("gl_fogdensity", "0.2");
357                 Cvar_Set("gl_fogred", "0.3");
358                 Cvar_Set("gl_foggreen", "0.3");
359                 Cvar_Set("gl_fogblue", "0.3");
360         }
361         r_refdef.fog_density = 0;
362         r_refdef.fog_red = 0;
363         r_refdef.fog_green = 0;
364         r_refdef.fog_blue = 0;
365         r_refdef.fog_alpha = 1;
366         r_refdef.fog_start = 0;
367         r_refdef.fog_end = 16384;
368         r_refdef.fog_height = 1<<30;
369         r_refdef.fog_fadedepth = 128;
370         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
371 }
372
373 static void R_BuildBlankTextures(void)
374 {
375         unsigned char data[4];
376         data[2] = 128; // normal X
377         data[1] = 128; // normal Y
378         data[0] = 255; // normal Z
379         data[3] = 255; // height
380         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 255;
382         data[1] = 255;
383         data[2] = 255;
384         data[3] = 255;
385         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 128;
387         data[1] = 128;
388         data[2] = 128;
389         data[3] = 255;
390         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391         data[0] = 0;
392         data[1] = 0;
393         data[2] = 0;
394         data[3] = 255;
395         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildNoTexture(void)
399 {
400         int x, y;
401         unsigned char pix[16][16][4];
402         // this makes a light grey/dark grey checkerboard texture
403         for (y = 0;y < 16;y++)
404         {
405                 for (x = 0;x < 16;x++)
406                 {
407                         if ((y < 8) ^ (x < 8))
408                         {
409                                 pix[y][x][0] = 128;
410                                 pix[y][x][1] = 128;
411                                 pix[y][x][2] = 128;
412                                 pix[y][x][3] = 255;
413                         }
414                         else
415                         {
416                                 pix[y][x][0] = 64;
417                                 pix[y][x][1] = 64;
418                                 pix[y][x][2] = 64;
419                                 pix[y][x][3] = 255;
420                         }
421                 }
422         }
423         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
424 }
425
426 static void R_BuildWhiteCube(void)
427 {
428         unsigned char data[6*1*1*4];
429         memset(data, 255, sizeof(data));
430         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildNormalizationCube(void)
434 {
435         int x, y, side;
436         vec3_t v;
437         vec_t s, t, intensity;
438 #define NORMSIZE 64
439         unsigned char *data;
440         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
441         for (side = 0;side < 6;side++)
442         {
443                 for (y = 0;y < NORMSIZE;y++)
444                 {
445                         for (x = 0;x < NORMSIZE;x++)
446                         {
447                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449                                 switch(side)
450                                 {
451                                 default:
452                                 case 0:
453                                         v[0] = 1;
454                                         v[1] = -t;
455                                         v[2] = -s;
456                                         break;
457                                 case 1:
458                                         v[0] = -1;
459                                         v[1] = -t;
460                                         v[2] = s;
461                                         break;
462                                 case 2:
463                                         v[0] = s;
464                                         v[1] = 1;
465                                         v[2] = t;
466                                         break;
467                                 case 3:
468                                         v[0] = s;
469                                         v[1] = -1;
470                                         v[2] = -t;
471                                         break;
472                                 case 4:
473                                         v[0] = s;
474                                         v[1] = -t;
475                                         v[2] = 1;
476                                         break;
477                                 case 5:
478                                         v[0] = -s;
479                                         v[1] = -t;
480                                         v[2] = -1;
481                                         break;
482                                 }
483                                 intensity = 127.0f / sqrt(DotProduct(v, v));
484                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
485                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
486                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
487                                 data[((side*64+y)*64+x)*4+3] = 255;
488                         }
489                 }
490         }
491         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
492         Mem_Free(data);
493 }
494
495 static void R_BuildFogTexture(void)
496 {
497         int x, b;
498 #define FOGWIDTH 256
499         unsigned char data1[FOGWIDTH][4];
500         //unsigned char data2[FOGWIDTH][4];
501         double d, r, alpha;
502
503         r_refdef.fogmasktable_start = r_refdef.fog_start;
504         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
505         r_refdef.fogmasktable_range = r_refdef.fogrange;
506         r_refdef.fogmasktable_density = r_refdef.fog_density;
507
508         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
509         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
510         {
511                 d = (x * r - r_refdef.fogmasktable_start);
512                 if(developer_extra.integer)
513                         Con_DPrintf("%f ", d);
514                 d = max(0, d);
515                 if (r_fog_exp2.integer)
516                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
517                 else
518                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
519                 if(developer_extra.integer)
520                         Con_DPrintf(" : %f ", alpha);
521                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
522                 if(developer_extra.integer)
523                         Con_DPrintf(" = %f\n", alpha);
524                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
525         }
526
527         for (x = 0;x < FOGWIDTH;x++)
528         {
529                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
530                 data1[x][0] = b;
531                 data1[x][1] = b;
532                 data1[x][2] = b;
533                 data1[x][3] = 255;
534                 //data2[x][0] = 255 - b;
535                 //data2[x][1] = 255 - b;
536                 //data2[x][2] = 255 - b;
537                 //data2[x][3] = 255;
538         }
539         if (r_texture_fogattenuation)
540         {
541                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543         }
544         else
545         {
546                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
547                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
548         }
549 }
550
551 static void R_BuildFogHeightTexture(void)
552 {
553         unsigned char *inpixels;
554         int size;
555         int x;
556         int y;
557         int j;
558         float c[4];
559         float f;
560         inpixels = NULL;
561         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
562         if (r_refdef.fogheighttexturename[0])
563                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
564         if (!inpixels)
565         {
566                 r_refdef.fog_height_tablesize = 0;
567                 if (r_texture_fogheighttexture)
568                         R_FreeTexture(r_texture_fogheighttexture);
569                 r_texture_fogheighttexture = NULL;
570                 if (r_refdef.fog_height_table2d)
571                         Mem_Free(r_refdef.fog_height_table2d);
572                 r_refdef.fog_height_table2d = NULL;
573                 if (r_refdef.fog_height_table1d)
574                         Mem_Free(r_refdef.fog_height_table1d);
575                 r_refdef.fog_height_table1d = NULL;
576                 return;
577         }
578         size = image_width;
579         r_refdef.fog_height_tablesize = size;
580         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
581         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
582         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
583         Mem_Free(inpixels);
584         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
585         // average fog color table accounting for every fog layer between a point
586         // and the camera.  (Note: attenuation is handled separately!)
587         for (y = 0;y < size;y++)
588         {
589                 for (x = 0;x < size;x++)
590                 {
591                         Vector4Clear(c);
592                         f = 0;
593                         if (x < y)
594                         {
595                                 for (j = x;j <= y;j++)
596                                 {
597                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
598                                         f++;
599                                 }
600                         }
601                         else
602                         {
603                                 for (j = x;j >= y;j--)
604                                 {
605                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
606                                         f++;
607                                 }
608                         }
609                         f = 1.0f / f;
610                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
613                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
614                 }
615         }
616         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
617 }
618
619 //=======================================================================================================================================================
620
621 static const char *builtinshaderstring =
622 #include "shader_glsl.h"
623 ;
624
625 const char *builtinhlslshaderstring =
626 #include "shader_hlsl.h"
627 ;
628
629 char *glslshaderstring = NULL;
630 char *hlslshaderstring = NULL;
631
632 //=======================================================================================================================================================
633
634 typedef struct shaderpermutationinfo_s
635 {
636         const char *pretext;
637         const char *name;
638 }
639 shaderpermutationinfo_t;
640
641 typedef struct shadermodeinfo_s
642 {
643         const char *vertexfilename;
644         const char *geometryfilename;
645         const char *fragmentfilename;
646         const char *pretext;
647         const char *name;
648 }
649 shadermodeinfo_t;
650
651 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
652 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
653 {
654         {"#define USEDIFFUSE\n", " diffuse"},
655         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
656         {"#define USEVIEWTINT\n", " viewtint"},
657         {"#define USECOLORMAPPING\n", " colormapping"},
658         {"#define USESATURATION\n", " saturation"},
659         {"#define USEFOGINSIDE\n", " foginside"},
660         {"#define USEFOGOUTSIDE\n", " fogoutside"},
661         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
662         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
663         {"#define USEGAMMARAMPS\n", " gammaramps"},
664         {"#define USECUBEFILTER\n", " cubefilter"},
665         {"#define USEGLOW\n", " glow"},
666         {"#define USEBLOOM\n", " bloom"},
667         {"#define USESPECULAR\n", " specular"},
668         {"#define USEPOSTPROCESSING\n", " postprocessing"},
669         {"#define USEREFLECTION\n", " reflection"},
670         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
671         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
672         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
673         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
674         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
675         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
676         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
677         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
678         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
679         {"#define USEALPHAKILL\n", " alphakill"},
680         {"#define USEREFLECTCUBE\n", " reflectcube"},
681         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
682         {"#define USEBOUNCEGRID\n", " bouncegrid"},
683         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
684         {"#define USETRIPPY\n", " trippy"},
685 };
686
687 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
688 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
689 {
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
707         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
708 };
709
710 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
711 {
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
729         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
730 };
731
732 struct r_glsl_permutation_s;
733 typedef struct r_glsl_permutation_s
734 {
735         /// hash lookup data
736         struct r_glsl_permutation_s *hashnext;
737         unsigned int mode;
738         unsigned int permutation;
739
740         /// indicates if we have tried compiling this permutation already
741         qboolean compiled;
742         /// 0 if compilation failed
743         int program;
744         // texture units assigned to each detected uniform
745         int tex_Texture_First;
746         int tex_Texture_Second;
747         int tex_Texture_GammaRamps;
748         int tex_Texture_Normal;
749         int tex_Texture_Color;
750         int tex_Texture_Gloss;
751         int tex_Texture_Glow;
752         int tex_Texture_SecondaryNormal;
753         int tex_Texture_SecondaryColor;
754         int tex_Texture_SecondaryGloss;
755         int tex_Texture_SecondaryGlow;
756         int tex_Texture_Pants;
757         int tex_Texture_Shirt;
758         int tex_Texture_FogHeightTexture;
759         int tex_Texture_FogMask;
760         int tex_Texture_Lightmap;
761         int tex_Texture_Deluxemap;
762         int tex_Texture_Attenuation;
763         int tex_Texture_Cube;
764         int tex_Texture_Refraction;
765         int tex_Texture_Reflection;
766         int tex_Texture_ShadowMap2D;
767         int tex_Texture_CubeProjection;
768         int tex_Texture_ScreenDepth;
769         int tex_Texture_ScreenNormalMap;
770         int tex_Texture_ScreenDiffuse;
771         int tex_Texture_ScreenSpecular;
772         int tex_Texture_ReflectMask;
773         int tex_Texture_ReflectCube;
774         int tex_Texture_BounceGrid;
775         /// locations of detected uniforms in program object, or -1 if not found
776         int loc_Texture_First;
777         int loc_Texture_Second;
778         int loc_Texture_GammaRamps;
779         int loc_Texture_Normal;
780         int loc_Texture_Color;
781         int loc_Texture_Gloss;
782         int loc_Texture_Glow;
783         int loc_Texture_SecondaryNormal;
784         int loc_Texture_SecondaryColor;
785         int loc_Texture_SecondaryGloss;
786         int loc_Texture_SecondaryGlow;
787         int loc_Texture_Pants;
788         int loc_Texture_Shirt;
789         int loc_Texture_FogHeightTexture;
790         int loc_Texture_FogMask;
791         int loc_Texture_Lightmap;
792         int loc_Texture_Deluxemap;
793         int loc_Texture_Attenuation;
794         int loc_Texture_Cube;
795         int loc_Texture_Refraction;
796         int loc_Texture_Reflection;
797         int loc_Texture_ShadowMap2D;
798         int loc_Texture_CubeProjection;
799         int loc_Texture_ScreenDepth;
800         int loc_Texture_ScreenNormalMap;
801         int loc_Texture_ScreenDiffuse;
802         int loc_Texture_ScreenSpecular;
803         int loc_Texture_ReflectMask;
804         int loc_Texture_ReflectCube;
805         int loc_Texture_BounceGrid;
806         int loc_Alpha;
807         int loc_BloomBlur_Parameters;
808         int loc_ClientTime;
809         int loc_Color_Ambient;
810         int loc_Color_Diffuse;
811         int loc_Color_Specular;
812         int loc_Color_Glow;
813         int loc_Color_Pants;
814         int loc_Color_Shirt;
815         int loc_DeferredColor_Ambient;
816         int loc_DeferredColor_Diffuse;
817         int loc_DeferredColor_Specular;
818         int loc_DeferredMod_Diffuse;
819         int loc_DeferredMod_Specular;
820         int loc_DistortScaleRefractReflect;
821         int loc_EyePosition;
822         int loc_FogColor;
823         int loc_FogHeightFade;
824         int loc_FogPlane;
825         int loc_FogPlaneViewDist;
826         int loc_FogRangeRecip;
827         int loc_LightColor;
828         int loc_LightDir;
829         int loc_LightPosition;
830         int loc_OffsetMapping_ScaleSteps;
831         int loc_OffsetMapping_LodDistance;
832         int loc_OffsetMapping_Bias;
833         int loc_PixelSize;
834         int loc_ReflectColor;
835         int loc_ReflectFactor;
836         int loc_ReflectOffset;
837         int loc_RefractColor;
838         int loc_Saturation;
839         int loc_ScreenCenterRefractReflect;
840         int loc_ScreenScaleRefractReflect;
841         int loc_ScreenToDepth;
842         int loc_ShadowMap_Parameters;
843         int loc_ShadowMap_TextureScale;
844         int loc_SpecularPower;
845         int loc_UserVec1;
846         int loc_UserVec2;
847         int loc_UserVec3;
848         int loc_UserVec4;
849         int loc_ViewTintColor;
850         int loc_ViewToLight;
851         int loc_ModelToLight;
852         int loc_TexMatrix;
853         int loc_BackgroundTexMatrix;
854         int loc_ModelViewProjectionMatrix;
855         int loc_ModelViewMatrix;
856         int loc_PixelToScreenTexCoord;
857         int loc_ModelToReflectCube;
858         int loc_ShadowMapMatrix;
859         int loc_BloomColorSubtract;
860         int loc_NormalmapScrollBlend;
861         int loc_BounceGridMatrix;
862         int loc_BounceGridIntensity;
863 }
864 r_glsl_permutation_t;
865
866 #define SHADERPERMUTATION_HASHSIZE 256
867
868
869 // non-degradable "lightweight" shader parameters to keep the permutations simpler
870 // these can NOT degrade! only use for simple stuff
871 enum
872 {
873         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
874         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
875         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
878         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
879         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
880         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
881 };
882 #define SHADERSTATICPARMS_COUNT 8
883
884 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
885 static int shaderstaticparms_count = 0;
886
887 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
888 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
889 qboolean R_CompileShader_CheckStaticParms(void)
890 {
891         static int r_compileshader_staticparms_save[1];
892         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
893         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
894
895         // detect all
896         if (r_glsl_saturation_redcompensate.integer)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
898         if (r_glsl_vertextextureblend_usebothalphas.integer)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
900         if (r_shadow_glossexact.integer)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
902         if (r_glsl_postprocess.integer)
903         {
904                 if (r_glsl_postprocess_uservec1_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
906                 if (r_glsl_postprocess_uservec2_enable.integer)
907                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
908                 if (r_glsl_postprocess_uservec3_enable.integer)
909                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
910                 if (r_glsl_postprocess_uservec4_enable.integer)
911                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
912         }
913         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
914                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
915         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
916 }
917
918 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
919         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
921         else \
922                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
923 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
924 {
925         shaderstaticparms_count = 0;
926
927         // emit all
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
936 }
937
938 /// information about each possible shader permutation
939 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
940 /// currently selected permutation
941 r_glsl_permutation_t *r_glsl_permutation;
942 /// storage for permutations linked in the hash table
943 memexpandablearray_t r_glsl_permutationarray;
944
945 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
946 {
947         //unsigned int hashdepth = 0;
948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
949         r_glsl_permutation_t *p;
950         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
951         {
952                 if (p->mode == mode && p->permutation == permutation)
953                 {
954                         //if (hashdepth > 10)
955                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956                         return p;
957                 }
958                 //hashdepth++;
959         }
960         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
961         p->mode = mode;
962         p->permutation = permutation;
963         p->hashnext = r_glsl_permutationhash[mode][hashindex];
964         r_glsl_permutationhash[mode][hashindex] = p;
965         //if (hashdepth > 10)
966         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
967         return p;
968 }
969
970 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 {
972         char *shaderstring;
973         if (!filename || !filename[0])
974                 return NULL;
975         if (!strcmp(filename, "glsl/default.glsl"))
976         {
977                 if (!glslshaderstring)
978                 {
979                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980                         if (glslshaderstring)
981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
982                         else
983                                 glslshaderstring = (char *)builtinshaderstring;
984                 }
985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
986                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987                 return shaderstring;
988         }
989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990         if (shaderstring)
991         {
992                 if (printfromdisknotice)
993                         Con_DPrintf("from disk %s... ", filename);
994                 return shaderstring;
995         }
996         return shaderstring;
997 }
998
999 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1000 {
1001         int i;
1002         int sampler;
1003         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1004         char *vertexstring, *geometrystring, *fragmentstring;
1005         char permutationname[256];
1006         int vertstrings_count = 0;
1007         int geomstrings_count = 0;
1008         int fragstrings_count = 0;
1009         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1011         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1012
1013         if (p->compiled)
1014                 return;
1015         p->compiled = true;
1016         p->program = 0;
1017
1018         permutationname[0] = 0;
1019         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1020         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1021         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1022
1023         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1024
1025         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1026         if(vid.support.gl20shaders130)
1027         {
1028                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1029                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1030                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1031                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1032                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1033                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034         }
1035
1036         // the first pretext is which type of shader to compile as
1037         // (later these will all be bound together as a program object)
1038         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1039         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1040         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1041
1042         // the second pretext is the mode (for example a light source)
1043         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1044         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1045         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1046         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1047
1048         // now add all the permutation pretexts
1049         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1050         {
1051                 if (permutation & (1<<i))
1052                 {
1053                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1057                 }
1058                 else
1059                 {
1060                         // keep line numbers correct
1061                         vertstrings_list[vertstrings_count++] = "\n";
1062                         geomstrings_list[geomstrings_count++] = "\n";
1063                         fragstrings_list[fragstrings_count++] = "\n";
1064                 }
1065         }
1066
1067         // add static parms
1068         R_CompileShader_AddStaticParms(mode, permutation);
1069         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         vertstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         geomstrings_count += shaderstaticparms_count;
1073         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1074         fragstrings_count += shaderstaticparms_count;
1075
1076         // now append the shader text itself
1077         vertstrings_list[vertstrings_count++] = vertexstring;
1078         geomstrings_list[geomstrings_count++] = geometrystring;
1079         fragstrings_list[fragstrings_count++] = fragmentstring;
1080
1081         // if any sources were NULL, clear the respective list
1082         if (!vertexstring)
1083                 vertstrings_count = 0;
1084         if (!geometrystring)
1085                 geomstrings_count = 0;
1086         if (!fragmentstring)
1087                 fragstrings_count = 0;
1088
1089         // compile the shader program
1090         if (vertstrings_count + geomstrings_count + fragstrings_count)
1091                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1092         if (p->program)
1093         {
1094                 CHECKGLERROR
1095                 qglUseProgram(p->program);CHECKGLERROR
1096                 // look up all the uniform variable names we care about, so we don't
1097                 // have to look them up every time we set them
1098
1099                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1100                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1101                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1102                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1103                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1104                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1105                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1106                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1107                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1108                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1109                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1110                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1111                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1112                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1113                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1114                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1115                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1116                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1117                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1118                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1119                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1120                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1121                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1122                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1123                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1124                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1125                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1126                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1127                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1128                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1129                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1130                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1131                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1132                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1133                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1134                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1135                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1136                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1137                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1138                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1139                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1140                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1141                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1142                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1143                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1144                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1145                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1146                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1147                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1148                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1149                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1150                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1151                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1152                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1153                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1154                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1155                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1156                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1157                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1158                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1159                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1160                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1161                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1162                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1163                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1164                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1165                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1166                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1167                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1168                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1169                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1170                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1171                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1172                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1173                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1174                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1175                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1176                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1177                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1178                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1179                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1180                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1181                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1182                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1183                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1184                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1185                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1186                 // initialize the samplers to refer to the texture units we use
1187                 p->tex_Texture_First = -1;
1188                 p->tex_Texture_Second = -1;
1189                 p->tex_Texture_GammaRamps = -1;
1190                 p->tex_Texture_Normal = -1;
1191                 p->tex_Texture_Color = -1;
1192                 p->tex_Texture_Gloss = -1;
1193                 p->tex_Texture_Glow = -1;
1194                 p->tex_Texture_SecondaryNormal = -1;
1195                 p->tex_Texture_SecondaryColor = -1;
1196                 p->tex_Texture_SecondaryGloss = -1;
1197                 p->tex_Texture_SecondaryGlow = -1;
1198                 p->tex_Texture_Pants = -1;
1199                 p->tex_Texture_Shirt = -1;
1200                 p->tex_Texture_FogHeightTexture = -1;
1201                 p->tex_Texture_FogMask = -1;
1202                 p->tex_Texture_Lightmap = -1;
1203                 p->tex_Texture_Deluxemap = -1;
1204                 p->tex_Texture_Attenuation = -1;
1205                 p->tex_Texture_Cube = -1;
1206                 p->tex_Texture_Refraction = -1;
1207                 p->tex_Texture_Reflection = -1;
1208                 p->tex_Texture_ShadowMap2D = -1;
1209                 p->tex_Texture_CubeProjection = -1;
1210                 p->tex_Texture_ScreenDepth = -1;
1211                 p->tex_Texture_ScreenNormalMap = -1;
1212                 p->tex_Texture_ScreenDiffuse = -1;
1213                 p->tex_Texture_ScreenSpecular = -1;
1214                 p->tex_Texture_ReflectMask = -1;
1215                 p->tex_Texture_ReflectCube = -1;
1216                 p->tex_Texture_BounceGrid = -1;
1217                 sampler = 0;
1218                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1219                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1220                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1221                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1222                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1223                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1224                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1228                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1229                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1230                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1231                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1232                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1233                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1234                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1235                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1236                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1237                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1238                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1239                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1240                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1243                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1244                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1245                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1246                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1247                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1248                 CHECKGLERROR
1249                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1250         }
1251         else
1252                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1253
1254         // free the strings
1255         if (vertexstring)
1256                 Mem_Free(vertexstring);
1257         if (geometrystring)
1258                 Mem_Free(geometrystring);
1259         if (fragmentstring)
1260                 Mem_Free(fragmentstring);
1261 }
1262
1263 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1264 {
1265         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1266         if (r_glsl_permutation != perm)
1267         {
1268                 r_glsl_permutation = perm;
1269                 if (!r_glsl_permutation->program)
1270                 {
1271                         if (!r_glsl_permutation->compiled)
1272                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                         if (!r_glsl_permutation->program)
1274                         {
1275                                 // remove features until we find a valid permutation
1276                                 int i;
1277                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1278                                 {
1279                                         // reduce i more quickly whenever it would not remove any bits
1280                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1281                                         if (!(permutation & j))
1282                                                 continue;
1283                                         permutation -= j;
1284                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1285                                         if (!r_glsl_permutation->compiled)
1286                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1287                                         if (r_glsl_permutation->program)
1288                                                 break;
1289                                 }
1290                                 if (i >= SHADERPERMUTATION_COUNT)
1291                                 {
1292                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1293                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1294                                         qglUseProgram(0);CHECKGLERROR
1295                                         return; // no bit left to clear, entire mode is broken
1296                                 }
1297                         }
1298                 }
1299                 CHECKGLERROR
1300                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1301         }
1302         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1303         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1304         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1305 }
1306
1307 #ifdef SUPPORTD3D
1308
1309 #ifdef SUPPORTD3D
1310 #include <d3d9.h>
1311 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1312 extern D3DCAPS9 vid_d3d9caps;
1313 #endif
1314
1315 struct r_hlsl_permutation_s;
1316 typedef struct r_hlsl_permutation_s
1317 {
1318         /// hash lookup data
1319         struct r_hlsl_permutation_s *hashnext;
1320         unsigned int mode;
1321         unsigned int permutation;
1322
1323         /// indicates if we have tried compiling this permutation already
1324         qboolean compiled;
1325         /// NULL if compilation failed
1326         IDirect3DVertexShader9 *vertexshader;
1327         IDirect3DPixelShader9 *pixelshader;
1328 }
1329 r_hlsl_permutation_t;
1330
1331 typedef enum D3DVSREGISTER_e
1332 {
1333         D3DVSREGISTER_TexMatrix = 0, // float4x4
1334         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1335         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1336         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1337         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1338         D3DVSREGISTER_ModelToLight = 20, // float4x4
1339         D3DVSREGISTER_EyePosition = 24,
1340         D3DVSREGISTER_FogPlane = 25,
1341         D3DVSREGISTER_LightDir = 26,
1342         D3DVSREGISTER_LightPosition = 27,
1343 }
1344 D3DVSREGISTER_t;
1345
1346 typedef enum D3DPSREGISTER_e
1347 {
1348         D3DPSREGISTER_Alpha = 0,
1349         D3DPSREGISTER_BloomBlur_Parameters = 1,
1350         D3DPSREGISTER_ClientTime = 2,
1351         D3DPSREGISTER_Color_Ambient = 3,
1352         D3DPSREGISTER_Color_Diffuse = 4,
1353         D3DPSREGISTER_Color_Specular = 5,
1354         D3DPSREGISTER_Color_Glow = 6,
1355         D3DPSREGISTER_Color_Pants = 7,
1356         D3DPSREGISTER_Color_Shirt = 8,
1357         D3DPSREGISTER_DeferredColor_Ambient = 9,
1358         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1359         D3DPSREGISTER_DeferredColor_Specular = 11,
1360         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1361         D3DPSREGISTER_DeferredMod_Specular = 13,
1362         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1363         D3DPSREGISTER_EyePosition = 15, // unused
1364         D3DPSREGISTER_FogColor = 16,
1365         D3DPSREGISTER_FogHeightFade = 17,
1366         D3DPSREGISTER_FogPlane = 18,
1367         D3DPSREGISTER_FogPlaneViewDist = 19,
1368         D3DPSREGISTER_FogRangeRecip = 20,
1369         D3DPSREGISTER_LightColor = 21,
1370         D3DPSREGISTER_LightDir = 22, // unused
1371         D3DPSREGISTER_LightPosition = 23,
1372         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1373         D3DPSREGISTER_PixelSize = 25,
1374         D3DPSREGISTER_ReflectColor = 26,
1375         D3DPSREGISTER_ReflectFactor = 27,
1376         D3DPSREGISTER_ReflectOffset = 28,
1377         D3DPSREGISTER_RefractColor = 29,
1378         D3DPSREGISTER_Saturation = 30,
1379         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1380         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1381         D3DPSREGISTER_ScreenToDepth = 33,
1382         D3DPSREGISTER_ShadowMap_Parameters = 34,
1383         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1384         D3DPSREGISTER_SpecularPower = 36,
1385         D3DPSREGISTER_UserVec1 = 37,
1386         D3DPSREGISTER_UserVec2 = 38,
1387         D3DPSREGISTER_UserVec3 = 39,
1388         D3DPSREGISTER_UserVec4 = 40,
1389         D3DPSREGISTER_ViewTintColor = 41,
1390         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1391         D3DPSREGISTER_BloomColorSubtract = 43,
1392         D3DPSREGISTER_ViewToLight = 44, // float4x4
1393         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1394         D3DPSREGISTER_NormalmapScrollBlend = 52,
1395         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1396         D3DPSREGISTER_OffsetMapping_Bias = 54,
1397         // next at 54
1398 }
1399 D3DPSREGISTER_t;
1400
1401 /// information about each possible shader permutation
1402 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1403 /// currently selected permutation
1404 r_hlsl_permutation_t *r_hlsl_permutation;
1405 /// storage for permutations linked in the hash table
1406 memexpandablearray_t r_hlsl_permutationarray;
1407
1408 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1409 {
1410         //unsigned int hashdepth = 0;
1411         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1412         r_hlsl_permutation_t *p;
1413         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1414         {
1415                 if (p->mode == mode && p->permutation == permutation)
1416                 {
1417                         //if (hashdepth > 10)
1418                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1419                         return p;
1420                 }
1421                 //hashdepth++;
1422         }
1423         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1424         p->mode = mode;
1425         p->permutation = permutation;
1426         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1427         r_hlsl_permutationhash[mode][hashindex] = p;
1428         //if (hashdepth > 10)
1429         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1430         return p;
1431 }
1432
1433 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1434 {
1435         char *shaderstring;
1436         if (!filename || !filename[0])
1437                 return NULL;
1438         if (!strcmp(filename, "hlsl/default.hlsl"))
1439         {
1440                 if (!hlslshaderstring)
1441                 {
1442                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1443                         if (hlslshaderstring)
1444                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1445                         else
1446                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1447                 }
1448                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1449                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1450                 return shaderstring;
1451         }
1452         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1453         if (shaderstring)
1454         {
1455                 if (printfromdisknotice)
1456                         Con_DPrintf("from disk %s... ", filename);
1457                 return shaderstring;
1458         }
1459         return shaderstring;
1460 }
1461
1462 #include <d3dx9.h>
1463 //#include <d3dx9shader.h>
1464 //#include <d3dx9mesh.h>
1465
1466 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1467 {
1468         DWORD *vsbin = NULL;
1469         DWORD *psbin = NULL;
1470         fs_offset_t vsbinsize;
1471         fs_offset_t psbinsize;
1472 //      IDirect3DVertexShader9 *vs = NULL;
1473 //      IDirect3DPixelShader9 *ps = NULL;
1474         ID3DXBuffer *vslog = NULL;
1475         ID3DXBuffer *vsbuffer = NULL;
1476         ID3DXConstantTable *vsconstanttable = NULL;
1477         ID3DXBuffer *pslog = NULL;
1478         ID3DXBuffer *psbuffer = NULL;
1479         ID3DXConstantTable *psconstanttable = NULL;
1480         int vsresult = 0;
1481         int psresult = 0;
1482         char temp[MAX_INPUTLINE];
1483         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1484         qboolean debugshader = gl_paranoid.integer != 0;
1485         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1486         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1487         if (!debugshader)
1488         {
1489                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1490                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1491         }
1492         if ((!vsbin && vertstring) || (!psbin && fragstring))
1493         {
1494                 const char* dllnames_d3dx9 [] =
1495                 {
1496                         "d3dx9_43.dll",
1497                         "d3dx9_42.dll",
1498                         "d3dx9_41.dll",
1499                         "d3dx9_40.dll",
1500                         "d3dx9_39.dll",
1501                         "d3dx9_38.dll",
1502                         "d3dx9_37.dll",
1503                         "d3dx9_36.dll",
1504                         "d3dx9_35.dll",
1505                         "d3dx9_34.dll",
1506                         "d3dx9_33.dll",
1507                         "d3dx9_32.dll",
1508                         "d3dx9_31.dll",
1509                         "d3dx9_30.dll",
1510                         "d3dx9_29.dll",
1511                         "d3dx9_28.dll",
1512                         "d3dx9_27.dll",
1513                         "d3dx9_26.dll",
1514                         "d3dx9_25.dll",
1515                         "d3dx9_24.dll",
1516                         NULL
1517                 };
1518                 dllhandle_t d3dx9_dll = NULL;
1519                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1521                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1522                 dllfunction_t d3dx9_dllfuncs[] =
1523                 {
1524                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1525                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1526                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1527                         {NULL, NULL}
1528                 };
1529                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1530                 {
1531                         DWORD shaderflags = 0;
1532                         if (debugshader)
1533                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1534                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1535                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1536                         if (vertstring && vertstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1541 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1543                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 }
1545                                 else
1546                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1547                                 if (vsbuffer)
1548                                 {
1549                                         vsbinsize = vsbuffer->GetBufferSize();
1550                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1551                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1552                                         vsbuffer->Release();
1553                                 }
1554                                 if (vslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1557                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         vslog->Release();
1559                                 }
1560                         }
1561                         if (fragstring && fragstring[0])
1562                         {
1563                                 if (debugshader)
1564                                 {
1565 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1566 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1567                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1568                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569                                 }
1570                                 else
1571                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1572                                 if (psbuffer)
1573                                 {
1574                                         psbinsize = psbuffer->GetBufferSize();
1575                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1576                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1577                                         psbuffer->Release();
1578                                 }
1579                                 if (pslog)
1580                                 {
1581                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1582                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1583                                         pslog->Release();
1584                                 }
1585                         }
1586                         Sys_UnloadLibrary(&d3dx9_dll);
1587                 }
1588                 else
1589                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1590         }
1591         if (vsbin && psbin)
1592         {
1593                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1594                 if (FAILED(vsresult))
1595                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1596                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1597                 if (FAILED(psresult))
1598                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1599         }
1600         // free the shader data
1601         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1602         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1603 }
1604
1605 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1606 {
1607         int i;
1608         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1609         int vertstring_length = 0;
1610         int geomstring_length = 0;
1611         int fragstring_length = 0;
1612         char *t;
1613         char *vertexstring, *geometrystring, *fragmentstring;
1614         char *vertstring, *geomstring, *fragstring;
1615         char permutationname[256];
1616         char cachename[256];
1617         int vertstrings_count = 0;
1618         int geomstrings_count = 0;
1619         int fragstrings_count = 0;
1620         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1621         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623
1624         if (p->compiled)
1625                 return;
1626         p->compiled = true;
1627         p->vertexshader = NULL;
1628         p->pixelshader = NULL;
1629
1630         permutationname[0] = 0;
1631         cachename[0] = 0;
1632         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1633         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1634         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1635
1636         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1637         strlcat(cachename, "hlsl/", sizeof(cachename));
1638
1639         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1640         vertstrings_count = 0;
1641         geomstrings_count = 0;
1642         fragstrings_count = 0;
1643         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1644         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1645         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1646
1647         // the first pretext is which type of shader to compile as
1648         // (later these will all be bound together as a program object)
1649         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1650         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1651         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1652
1653         // the second pretext is the mode (for example a light source)
1654         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1655         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1656         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1657         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1658         strlcat(cachename, modeinfo->name, sizeof(cachename));
1659
1660         // now add all the permutation pretexts
1661         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1662         {
1663                 if (permutation & (1<<i))
1664                 {
1665                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1668                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1669                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1670                 }
1671                 else
1672                 {
1673                         // keep line numbers correct
1674                         vertstrings_list[vertstrings_count++] = "\n";
1675                         geomstrings_list[geomstrings_count++] = "\n";
1676                         fragstrings_list[fragstrings_count++] = "\n";
1677                 }
1678         }
1679
1680         // add static parms
1681         R_CompileShader_AddStaticParms(mode, permutation);
1682         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         vertstrings_count += shaderstaticparms_count;
1684         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         geomstrings_count += shaderstaticparms_count;
1686         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1687         fragstrings_count += shaderstaticparms_count;
1688
1689         // replace spaces in the cachename with _ characters
1690         for (i = 0;cachename[i];i++)
1691                 if (cachename[i] == ' ')
1692                         cachename[i] = '_';
1693
1694         // now append the shader text itself
1695         vertstrings_list[vertstrings_count++] = vertexstring;
1696         geomstrings_list[geomstrings_count++] = geometrystring;
1697         fragstrings_list[fragstrings_count++] = fragmentstring;
1698
1699         // if any sources were NULL, clear the respective list
1700         if (!vertexstring)
1701                 vertstrings_count = 0;
1702         if (!geometrystring)
1703                 geomstrings_count = 0;
1704         if (!fragmentstring)
1705                 fragstrings_count = 0;
1706
1707         vertstring_length = 0;
1708         for (i = 0;i < vertstrings_count;i++)
1709                 vertstring_length += strlen(vertstrings_list[i]);
1710         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1711         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1712                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1713
1714         geomstring_length = 0;
1715         for (i = 0;i < geomstrings_count;i++)
1716                 geomstring_length += strlen(geomstrings_list[i]);
1717         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1718         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1719                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1720
1721         fragstring_length = 0;
1722         for (i = 0;i < fragstrings_count;i++)
1723                 fragstring_length += strlen(fragstrings_list[i]);
1724         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1725         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1726                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1727
1728         // try to load the cached shader, or generate one
1729         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1730
1731         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1732                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1733         else
1734                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1735
1736         // free the strings
1737         if (vertstring)
1738                 Mem_Free(vertstring);
1739         if (geomstring)
1740                 Mem_Free(geomstring);
1741         if (fragstring)
1742                 Mem_Free(fragstring);
1743         if (vertexstring)
1744                 Mem_Free(vertexstring);
1745         if (geometrystring)
1746                 Mem_Free(geometrystring);
1747         if (fragmentstring)
1748                 Mem_Free(fragmentstring);
1749 }
1750
1751 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1752 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1753 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);}
1754 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);}
1755 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);}
1756 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);}
1757
1758 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1759 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1760 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);}
1761 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);}
1762 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);}
1763 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);}
1764
1765 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1766 {
1767         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1768         if (r_hlsl_permutation != perm)
1769         {
1770                 r_hlsl_permutation = perm;
1771                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1772                 {
1773                         if (!r_hlsl_permutation->compiled)
1774                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1776                         {
1777                                 // remove features until we find a valid permutation
1778                                 int i;
1779                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1780                                 {
1781                                         // reduce i more quickly whenever it would not remove any bits
1782                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1783                                         if (!(permutation & j))
1784                                                 continue;
1785                                         permutation -= j;
1786                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1787                                         if (!r_hlsl_permutation->compiled)
1788                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1789                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1790                                                 break;
1791                                 }
1792                                 if (i >= SHADERPERMUTATION_COUNT)
1793                                 {
1794                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1795                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1796                                         return; // no bit left to clear, entire mode is broken
1797                                 }
1798                         }
1799                 }
1800                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1801                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1802         }
1803         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1804         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1805         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1806 }
1807 #endif
1808
1809 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1810 {
1811         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1812         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1813         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1814         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1815 }
1816
1817 void R_GLSL_Restart_f(void)
1818 {
1819         unsigned int i, limit;
1820         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1821                 Mem_Free(glslshaderstring);
1822         glslshaderstring = NULL;
1823         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1824                 Mem_Free(hlslshaderstring);
1825         hlslshaderstring = NULL;
1826         switch(vid.renderpath)
1827         {
1828         case RENDERPATH_D3D9:
1829 #ifdef SUPPORTD3D
1830                 {
1831                         r_hlsl_permutation_t *p;
1832                         r_hlsl_permutation = NULL;
1833                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1834                         for (i = 0;i < limit;i++)
1835                         {
1836                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1837                                 {
1838                                         if (p->vertexshader)
1839                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1840                                         if (p->pixelshader)
1841                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1842                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1843                                 }
1844                         }
1845                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1846                 }
1847 #endif
1848                 break;
1849         case RENDERPATH_D3D10:
1850                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851                 break;
1852         case RENDERPATH_D3D11:
1853                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1854                 break;
1855         case RENDERPATH_GL20:
1856         case RENDERPATH_GLES2:
1857                 {
1858                         r_glsl_permutation_t *p;
1859                         r_glsl_permutation = NULL;
1860                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1861                         for (i = 0;i < limit;i++)
1862                         {
1863                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1864                                 {
1865                                         GL_Backend_FreeProgram(p->program);
1866                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1867                                 }
1868                         }
1869                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1870                 }
1871                 break;
1872         case RENDERPATH_GL11:
1873         case RENDERPATH_GL13:
1874         case RENDERPATH_GLES1:
1875                 break;
1876         case RENDERPATH_SOFT:
1877                 break;
1878         }
1879 }
1880
1881 void R_GLSL_DumpShader_f(void)
1882 {
1883         int i;
1884         qfile_t *file;
1885
1886         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1887         if (file)
1888         {
1889                 FS_Print(file, "/* The engine may define the following macros:\n");
1890                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1891                 for (i = 0;i < SHADERMODE_COUNT;i++)
1892                         FS_Print(file, glslshadermodeinfo[i].pretext);
1893                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1894                         FS_Print(file, shaderpermutationinfo[i].pretext);
1895                 FS_Print(file, "*/\n");
1896                 FS_Print(file, builtinshaderstring);
1897                 FS_Close(file);
1898                 Con_Printf("glsl/default.glsl written\n");
1899         }
1900         else
1901                 Con_Printf("failed to write to glsl/default.glsl\n");
1902
1903         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1904         if (file)
1905         {
1906                 FS_Print(file, "/* The engine may define the following macros:\n");
1907                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1908                 for (i = 0;i < SHADERMODE_COUNT;i++)
1909                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1910                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1911                         FS_Print(file, shaderpermutationinfo[i].pretext);
1912                 FS_Print(file, "*/\n");
1913                 FS_Print(file, builtinhlslshaderstring);
1914                 FS_Close(file);
1915                 Con_Printf("hlsl/default.hlsl written\n");
1916         }
1917         else
1918                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1919 }
1920
1921 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1922 {
1923         unsigned int permutation = 0;
1924         if (r_trippy.integer && !notrippy)
1925                 permutation |= SHADERPERMUTATION_TRIPPY;
1926         permutation |= SHADERPERMUTATION_VIEWTINT;
1927         if (first)
1928                 permutation |= SHADERPERMUTATION_DIFFUSE;
1929         if (second)
1930                 permutation |= SHADERPERMUTATION_SPECULAR;
1931         if (texturemode == GL_MODULATE)
1932                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1933         else if (texturemode == GL_ADD)
1934                 permutation |= SHADERPERMUTATION_GLOW;
1935         else if (texturemode == GL_DECAL)
1936                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1937         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1938                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1939         if (!second)
1940                 texturemode = GL_MODULATE;
1941         if (vid.allowalphatocoverage)
1942                 GL_AlphaToCoverage(false);
1943         switch (vid.renderpath)
1944         {
1945         case RENDERPATH_D3D9:
1946 #ifdef SUPPORTD3D
1947                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1966                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, first );
1971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1972                 R_Mesh_TexBind(1, second);
1973                 if (second)
1974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1975                 break;
1976         case RENDERPATH_GL11:
1977                 R_Mesh_TexBind(0, first );
1978                 break;
1979         case RENDERPATH_SOFT:
1980                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1981                 R_Mesh_TexBind(GL20TU_FIRST , first );
1982                 R_Mesh_TexBind(GL20TU_SECOND, second);
1983                 break;
1984         }
1985 }
1986
1987 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1988 {
1989         unsigned int permutation = 0;
1990         if (r_trippy.integer && !notrippy)
1991                 permutation |= SHADERPERMUTATION_TRIPPY;
1992         if (vid.allowalphatocoverage)
1993                 GL_AlphaToCoverage(false);
1994         switch (vid.renderpath)
1995         {
1996         case RENDERPATH_D3D9:
1997 #ifdef SUPPORTD3D
1998                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1999 #endif
2000                 break;
2001         case RENDERPATH_D3D10:
2002                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2003                 break;
2004         case RENDERPATH_D3D11:
2005                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2006                 break;
2007         case RENDERPATH_GL20:
2008         case RENDERPATH_GLES2:
2009                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2010                 break;
2011         case RENDERPATH_GL13:
2012         case RENDERPATH_GLES1:
2013                 R_Mesh_TexBind(0, 0);
2014                 R_Mesh_TexBind(1, 0);
2015                 break;
2016         case RENDERPATH_GL11:
2017                 R_Mesh_TexBind(0, 0);
2018                 break;
2019         case RENDERPATH_SOFT:
2020                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2021                 break;
2022         }
2023 }
2024
2025 void R_SetupShader_ShowDepth(qboolean notrippy)
2026 {
2027         int permutation = 0;
2028         if (r_trippy.integer && !notrippy)
2029                 permutation |= SHADERPERMUTATION_TRIPPY;
2030         if (vid.allowalphatocoverage)
2031                 GL_AlphaToCoverage(false);
2032         switch (vid.renderpath)
2033         {
2034         case RENDERPATH_D3D9:
2035 #ifdef SUPPORTHLSL
2036                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2037 #endif
2038                 break;
2039         case RENDERPATH_D3D10:
2040                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2041                 break;
2042         case RENDERPATH_D3D11:
2043                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2044                 break;
2045         case RENDERPATH_GL20:
2046         case RENDERPATH_GLES2:
2047                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2048                 break;
2049         case RENDERPATH_GL13:
2050         case RENDERPATH_GLES1:
2051                 break;
2052         case RENDERPATH_GL11:
2053                 break;
2054         case RENDERPATH_SOFT:
2055                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2056                 break;
2057         }
2058 }
2059
2060 extern qboolean r_shadow_usingdeferredprepass;
2061 extern cvar_t r_shadow_deferred_8bitrange;
2062 extern rtexture_t *r_shadow_attenuationgradienttexture;
2063 extern rtexture_t *r_shadow_attenuation2dtexture;
2064 extern rtexture_t *r_shadow_attenuation3dtexture;
2065 extern qboolean r_shadow_usingshadowmap2d;
2066 extern qboolean r_shadow_usingshadowmaportho;
2067 extern float r_shadow_shadowmap_texturescale[2];
2068 extern float r_shadow_shadowmap_parameters[4];
2069 extern qboolean r_shadow_shadowmapvsdct;
2070 extern qboolean r_shadow_shadowmapsampler;
2071 extern int r_shadow_shadowmappcf;
2072 extern rtexture_t *r_shadow_shadowmap2dtexture;
2073 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2074 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2075 extern matrix4x4_t r_shadow_shadowmapmatrix;
2076 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2077 extern int r_shadow_prepass_width;
2078 extern int r_shadow_prepass_height;
2079 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2080 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2081 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2082 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2083 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2084
2085 #define BLENDFUNC_ALLOWS_COLORMOD      1
2086 #define BLENDFUNC_ALLOWS_FOG           2
2087 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2088 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2089 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2090 static int R_BlendFuncFlags(int src, int dst)
2091 {
2092         int r = 0;
2093
2094         // a blendfunc allows colormod if:
2095         // a) it can never keep the destination pixel invariant, or
2096         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2097         // this is to prevent unintended side effects from colormod
2098
2099         // a blendfunc allows fog if:
2100         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2101         // this is to prevent unintended side effects from fog
2102
2103         // these checks are the output of fogeval.pl
2104
2105         r |= BLENDFUNC_ALLOWS_COLORMOD;
2106         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2107         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2115         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2118         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2124         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2125         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2127
2128         return r;
2129 }
2130
2131 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)
2132 {
2133         // select a permutation of the lighting shader appropriate to this
2134         // combination of texture, entity, light source, and fogging, only use the
2135         // minimum features necessary to avoid wasting rendering time in the
2136         // fragment shader on features that are not being used
2137         unsigned int permutation = 0;
2138         unsigned int mode = 0;
2139         int blendfuncflags;
2140         static float dummy_colormod[3] = {1, 1, 1};
2141         float *colormod = rsurface.colormod;
2142         float m16f[16];
2143         matrix4x4_t tempmatrix;
2144         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2145         if (r_trippy.integer && !notrippy)
2146                 permutation |= SHADERPERMUTATION_TRIPPY;
2147         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2148                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2149         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2150                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2151         if (rsurfacepass == RSURFPASS_BACKGROUND)
2152         {
2153                 // distorted background
2154                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2155                 {
2156                         mode = SHADERMODE_WATER;
2157                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2158                         {
2159                                 // this is the right thing to do for wateralpha
2160                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2161                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2162                         }
2163                         else
2164                         {
2165                                 // this is the right thing to do for entity alpha
2166                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2167                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168                         }
2169                 }
2170                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2171                 {
2172                         mode = SHADERMODE_REFRACTION;
2173                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2174                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2175                 }
2176                 else
2177                 {
2178                         mode = SHADERMODE_GENERIC;
2179                         permutation |= SHADERPERMUTATION_DIFFUSE;
2180                         GL_BlendFunc(GL_ONE, GL_ZERO);
2181                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2182                 }
2183                 if (vid.allowalphatocoverage)
2184                         GL_AlphaToCoverage(false);
2185         }
2186         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
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                 // normalmap (deferred prepass), may use alpha test on diffuse
2201                 mode = SHADERMODE_DEFERREDGEOMETRY;
2202                 GL_BlendFunc(GL_ONE, GL_ZERO);
2203                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2204                 if (vid.allowalphatocoverage)
2205                         GL_AlphaToCoverage(false);
2206         }
2207         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2208         {
2209                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2210                 {
2211                         switch(rsurface.texture->offsetmapping)
2212                         {
2213                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2214                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2215                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216                         case OFFSETMAPPING_OFF: break;
2217                         }
2218                 }
2219                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2220                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2221                 // light source
2222                 mode = SHADERMODE_LIGHTSOURCE;
2223                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2224                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2225                 if (diffusescale > 0)
2226                         permutation |= SHADERPERMUTATION_DIFFUSE;
2227                 if (specularscale > 0)
2228                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2229                 if (r_refdef.fogenabled)
2230                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2231                 if (rsurface.texture->colormapping)
2232                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2233                 if (r_shadow_usingshadowmap2d)
2234                 {
2235                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2236                         if(r_shadow_shadowmapvsdct)
2237                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2238
2239                         if (r_shadow_shadowmapsampler)
2240                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2241                         if (r_shadow_shadowmappcf > 1)
2242                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2243                         else if (r_shadow_shadowmappcf)
2244                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2245                 }
2246                 if (rsurface.texture->reflectmasktexture)
2247                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2248                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2249                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2250                 if (vid.allowalphatocoverage)
2251                         GL_AlphaToCoverage(false);
2252         }
2253         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2254         {
2255                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2256                 {
2257                         switch(rsurface.texture->offsetmapping)
2258                         {
2259                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2260                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2261                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262                         case OFFSETMAPPING_OFF: break;
2263                         }
2264                 }
2265                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2266                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2267                 // unshaded geometry (fullbright or ambient model lighting)
2268                 mode = SHADERMODE_FLATCOLOR;
2269                 ambientscale = diffusescale = specularscale = 0;
2270                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2271                         permutation |= SHADERPERMUTATION_GLOW;
2272                 if (r_refdef.fogenabled)
2273                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2274                 if (rsurface.texture->colormapping)
2275                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2276                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2277                 {
2278                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2279                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2280
2281                         if (r_shadow_shadowmapsampler)
2282                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2283                         if (r_shadow_shadowmappcf > 1)
2284                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2285                         else if (r_shadow_shadowmappcf)
2286                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2289                         permutation |= SHADERPERMUTATION_REFLECTION;
2290                 if (rsurface.texture->reflectmasktexture)
2291                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2292                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2293                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294                 // when using alphatocoverage, we don't need alphakill
2295                 if (vid.allowalphatocoverage)
2296                 {
2297                         if (r_transparent_alphatocoverage.integer)
2298                         {
2299                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2300                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2301                         }
2302                         else
2303                                 GL_AlphaToCoverage(false);
2304                 }
2305         }
2306         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2307         {
2308                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2309                 {
2310                         switch(rsurface.texture->offsetmapping)
2311                         {
2312                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2313                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2314                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_OFF: break;
2316                         }
2317                 }
2318                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2319                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2320                 // directional model lighting
2321                 mode = SHADERMODE_LIGHTDIRECTION;
2322                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2323                         permutation |= SHADERPERMUTATION_GLOW;
2324                 permutation |= SHADERPERMUTATION_DIFFUSE;
2325                 if (specularscale > 0)
2326                         permutation |= SHADERPERMUTATION_SPECULAR;
2327                 if (r_refdef.fogenabled)
2328                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2329                 if (rsurface.texture->colormapping)
2330                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2331                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2332                 {
2333                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2334                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2335
2336                         if (r_shadow_shadowmapsampler)
2337                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2338                         if (r_shadow_shadowmappcf > 1)
2339                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2340                         else if (r_shadow_shadowmappcf)
2341                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344                         permutation |= SHADERPERMUTATION_REFLECTION;
2345                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2347                 if (rsurface.texture->reflectmasktexture)
2348                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2349                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2350                 {
2351                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2352                         if (r_shadow_bouncegriddirectional)
2353                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2354                 }
2355                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 // when using alphatocoverage, we don't need alphakill
2358                 if (vid.allowalphatocoverage)
2359                 {
2360                         if (r_transparent_alphatocoverage.integer)
2361                         {
2362                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2363                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364                         }
2365                         else
2366                                 GL_AlphaToCoverage(false);
2367                 }
2368         }
2369         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2370         {
2371                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2372                 {
2373                         switch(rsurface.texture->offsetmapping)
2374                         {
2375                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2376                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_OFF: break;
2379                         }
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2383                 // ambient model lighting
2384                 mode = SHADERMODE_LIGHTDIRECTION;
2385                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2386                         permutation |= SHADERPERMUTATION_GLOW;
2387                 if (r_refdef.fogenabled)
2388                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2389                 if (rsurface.texture->colormapping)
2390                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2391                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2392                 {
2393                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2394                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2395
2396                         if (r_shadow_shadowmapsampler)
2397                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2398                         if (r_shadow_shadowmappcf > 1)
2399                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2400                         else if (r_shadow_shadowmappcf)
2401                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2402                 }
2403                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2404                         permutation |= SHADERPERMUTATION_REFLECTION;
2405                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2406                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2407                 if (rsurface.texture->reflectmasktexture)
2408                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2409                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2410                 {
2411                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2412                         if (r_shadow_bouncegriddirectional)
2413                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2414                 }
2415                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417                 // when using alphatocoverage, we don't need alphakill
2418                 if (vid.allowalphatocoverage)
2419                 {
2420                         if (r_transparent_alphatocoverage.integer)
2421                         {
2422                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2423                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2424                         }
2425                         else
2426                                 GL_AlphaToCoverage(false);
2427                 }
2428         }
2429         else
2430         {
2431                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2432                 {
2433                         switch(rsurface.texture->offsetmapping)
2434                         {
2435                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2436                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2438                         case OFFSETMAPPING_OFF: break;
2439                         }
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2442                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2443                 // lightmapped wall
2444                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmapsampler)
2456                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2457                         if (r_shadow_shadowmappcf > 1)
2458                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2459                         else if (r_shadow_shadowmappcf)
2460                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2461                 }
2462                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2463                         permutation |= SHADERPERMUTATION_REFLECTION;
2464                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2465                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2466                 if (rsurface.texture->reflectmasktexture)
2467                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2468                 if (FAKELIGHT_ENABLED)
2469                 {
2470                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2471                         mode = SHADERMODE_FAKELIGHT;
2472                         permutation |= SHADERPERMUTATION_DIFFUSE;
2473                         if (specularscale > 0)
2474                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2475                 }
2476                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2477                 {
2478                         // deluxemapping (light direction texture)
2479                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2481                         else
2482                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2483                         permutation |= SHADERPERMUTATION_DIFFUSE;
2484                         if (specularscale > 0)
2485                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2486                 }
2487                 else if (r_glsl_deluxemapping.integer >= 2)
2488                 {
2489                         // fake deluxemapping (uniform light direction in tangentspace)
2490                         if (rsurface.uselightmaptexture)
2491                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2492                         else
2493                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2494                         permutation |= SHADERPERMUTATION_DIFFUSE;
2495                         if (specularscale > 0)
2496                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2497                 }
2498                 else if (rsurface.uselightmaptexture)
2499                 {
2500                         // ordinary lightmapping (q1bsp, q3bsp)
2501                         mode = SHADERMODE_LIGHTMAP;
2502                 }
2503                 else
2504                 {
2505                         // ordinary vertex coloring (q3bsp)
2506                         mode = SHADERMODE_VERTEXCOLOR;
2507                 }
2508                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2509                 {
2510                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2511                         if (r_shadow_bouncegriddirectional)
2512                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2513                 }
2514                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2515                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2516                 // when using alphatocoverage, we don't need alphakill
2517                 if (vid.allowalphatocoverage)
2518                 {
2519                         if (r_transparent_alphatocoverage.integer)
2520                         {
2521                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2522                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2523                         }
2524                         else
2525                                 GL_AlphaToCoverage(false);
2526                 }
2527         }
2528         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2529                 colormod = dummy_colormod;
2530         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2531                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2532         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2533                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2534         switch(vid.renderpath)
2535         {
2536         case RENDERPATH_D3D9:
2537 #ifdef SUPPORTD3D
2538                 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);
2539                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2540                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2542                 if (mode == SHADERMODE_LIGHTSOURCE)
2543                 {
2544                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2545                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2546                 }
2547                 else
2548                 {
2549                         if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2552                         }
2553                 }
2554                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2555                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2556                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2557                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2558                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2559
2560                 if (mode == SHADERMODE_LIGHTSOURCE)
2561                 {
2562                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2565                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2567
2568                         // additive passes are only darkened by fog, not tinted
2569                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2571                 }
2572                 else
2573                 {
2574                         if (mode == SHADERMODE_FLATCOLOR)
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2577                         }
2578                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2579                         {
2580                                 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]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2582                                 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);
2583                                 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);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2587                         }
2588                         else
2589                         {
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2592                                 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);
2593                                 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);
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2595                         }
2596                         // additive passes are only darkened by fog, not tinted
2597                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2598                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2599                         else
2600                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2601                         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);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2604                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2605                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2606                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2607                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2608                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2609                         if (mode == SHADERMODE_WATER)
2610                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2611                 }
2612                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2613                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2614                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2616                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2617                 if (rsurface.texture->pantstexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2621                 if (rsurface.texture->shirttexture)
2622                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2623                 else
2624                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2626                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2627                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2628                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2629                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2630                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2631                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2632                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2633                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2634                         );
2635                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2636                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2637                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2638                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2639
2640                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2641                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2642                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2643                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2648                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2649                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2650                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2651                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2652                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2653                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2654                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2655                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2656                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2657                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2658                 {
2659                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2660                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2661                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662                 }
2663                 else
2664                 {
2665                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2666                 }
2667 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2668 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2669                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2671                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2672                 {
2673                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2674                         if (rsurface.rtlight)
2675                         {
2676                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2677                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2678                         }
2679                 }
2680 #endif
2681                 break;
2682         case RENDERPATH_D3D10:
2683                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2684                 break;
2685         case RENDERPATH_D3D11:
2686                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2687                 break;
2688         case RENDERPATH_GL20:
2689         case RENDERPATH_GLES2:
2690                 if (!vid.useinterleavedarrays)
2691                 {
2692                         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);
2693                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2694                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2700                 }
2701                 else
2702                 {
2703                         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);
2704                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2705                 }
2706                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2707                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2708                 if (mode == SHADERMODE_LIGHTSOURCE)
2709                 {
2710                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2711                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2712                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2713                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2714                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2715                         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);
2716         
2717                         // additive passes are only darkened by fog, not tinted
2718                         if (r_glsl_permutation->loc_FogColor >= 0)
2719                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2720                         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);
2721                 }
2722                 else
2723                 {
2724                         if (mode == SHADERMODE_FLATCOLOR)
2725                         {
2726                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2727                         }
2728                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2729                         {
2730                                 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]);
2731                                 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]);
2732                                 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);
2733                                 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);
2734                                 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);
2735                                 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]);
2736                                 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]);
2737                         }
2738                         else
2739                         {
2740                                 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]);
2741                                 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]);
2742                                 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);
2743                                 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);
2744                                 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);
2745                         }
2746                         // additive passes are only darkened by fog, not tinted
2747                         if (r_glsl_permutation->loc_FogColor >= 0)
2748                         {
2749                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2750                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2751                                 else
2752                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2753                         }
2754                         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);
2755                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2756                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2757                         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]);
2758                         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]);
2759                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2760                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2761                         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);
2762                         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]);
2763                 }
2764                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2765                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2766                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2767                 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]);
2768                 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]);
2769
2770                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2771                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2772                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2773                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2774                 {
2775                         if (rsurface.texture->pantstexture)
2776                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2777                         else
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2779                 }
2780                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2781                 {
2782                         if (rsurface.texture->shirttexture)
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2784                         else
2785                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2786                 }
2787                 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]);
2788                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2789                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2790                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2791                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2792                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2793                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2794                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2795                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2796                         );
2797                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2798                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2799                 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]);
2800                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2801                 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);}
2802                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2803
2804                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2805                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2806                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2807                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2808                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2809                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2810                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2811                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2813                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2814                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2815                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2816                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2817                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2818                 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);
2819                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2820                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2821                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2822                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2823                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2824                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2825                 {
2826                         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);
2827                         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);
2828                         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);
2829                 }
2830                 else
2831                 {
2832                         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);
2833                 }
2834                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2835                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2836                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2837                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2838                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2839                 {
2840                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2841                         if (rsurface.rtlight)
2842                         {
2843                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2844                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2845                         }
2846                 }
2847                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2848                 CHECKGLERROR
2849                 break;
2850         case RENDERPATH_GL11:
2851         case RENDERPATH_GL13:
2852         case RENDERPATH_GLES1:
2853                 break;
2854         case RENDERPATH_SOFT:
2855                 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);
2856                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2857                 R_SetupShader_SetPermutationSoft(mode, permutation);
2858                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2859                 if (mode == SHADERMODE_LIGHTSOURCE)
2860                 {
2861                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2865                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2866                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2867         
2868                         // additive passes are only darkened by fog, not tinted
2869                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2870                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2871                 }
2872                 else
2873                 {
2874                         if (mode == SHADERMODE_FLATCOLOR)
2875                         {
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2877                         }
2878                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2879                         {
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2882                                 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);
2883                                 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);
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2885                                 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]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2887                         }
2888                         else
2889                         {
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2892                                 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);
2893                                 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);
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2895                         }
2896                         // additive passes are only darkened by fog, not tinted
2897                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2899                         else
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2901                         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);
2902                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2904                         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]);
2905                         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]);
2906                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2907                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2908                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2909                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2910                 }
2911                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2912                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2913                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2914                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2915                 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]);
2916
2917                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2919                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2920                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2921                 {
2922                         if (rsurface.texture->pantstexture)
2923                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2924                         else
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2926                 }
2927                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2928                 {
2929                         if (rsurface.texture->shirttexture)
2930                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2931                         else
2932                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2933                 }
2934                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2935                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2936                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2937                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2938                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2939                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2940                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2941                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2942                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2943                         );
2944                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2945                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2946                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2947                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2948
2949                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2950                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2951                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2952                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2953                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2954                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2955                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2956                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2957                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2958                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2959                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2960                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2961                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2962                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2963                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2964                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2965                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2966                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2967                 {
2968                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2969                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2970                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2971                 }
2972                 else
2973                 {
2974                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2975                 }
2976 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2977 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2978                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2979                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2980                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2981                 {
2982                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2983                         if (rsurface.rtlight)
2984                         {
2985                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2986                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2987                         }
2988                 }
2989                 break;
2990         }
2991 }
2992
2993 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2994 {
2995         // select a permutation of the lighting shader appropriate to this
2996         // combination of texture, entity, light source, and fogging, only use the
2997         // minimum features necessary to avoid wasting rendering time in the
2998         // fragment shader on features that are not being used
2999         unsigned int permutation = 0;
3000         unsigned int mode = 0;
3001         const float *lightcolorbase = rtlight->currentcolor;
3002         float ambientscale = rtlight->ambientscale;
3003         float diffusescale = rtlight->diffusescale;
3004         float specularscale = rtlight->specularscale;
3005         // this is the location of the light in view space
3006         vec3_t viewlightorigin;
3007         // this transforms from view space (camera) to light space (cubemap)
3008         matrix4x4_t viewtolight;
3009         matrix4x4_t lighttoview;
3010         float viewtolight16f[16];
3011         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3012         // light source
3013         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3014         if (rtlight->currentcubemap != r_texture_whitecube)
3015                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3016         if (diffusescale > 0)
3017                 permutation |= SHADERPERMUTATION_DIFFUSE;
3018         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3019                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3020         if (r_shadow_usingshadowmap2d)
3021         {
3022                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3023                 if (r_shadow_shadowmapvsdct)
3024                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3025
3026                 if (r_shadow_shadowmapsampler)
3027                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3028                 if (r_shadow_shadowmappcf > 1)
3029                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3030                 else if (r_shadow_shadowmappcf)
3031                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3032         }
3033         if (vid.allowalphatocoverage)
3034                 GL_AlphaToCoverage(false);
3035         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3036         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3037         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3038         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3039         switch(vid.renderpath)
3040         {
3041         case RENDERPATH_D3D9:
3042 #ifdef SUPPORTD3D
3043                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3044                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3047                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3048                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3049                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3050                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3051                 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);
3052                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3054
3055                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3056                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3057                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3059                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3060                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3061 #endif
3062                 break;
3063         case RENDERPATH_D3D10:
3064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3065                 break;
3066         case RENDERPATH_D3D11:
3067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3068                 break;
3069         case RENDERPATH_GL20:
3070         case RENDERPATH_GLES2:
3071                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3072                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3073                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3074                 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);
3075                 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);
3076                 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);
3077                 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]);
3078                 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]);
3079                 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);
3080                 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]);
3081                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3082
3083                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3084                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3085                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3086                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3087                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3088                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3089                 break;
3090         case RENDERPATH_GL11:
3091         case RENDERPATH_GL13:
3092         case RENDERPATH_GLES1:
3093                 break;
3094         case RENDERPATH_SOFT:
3095                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3096                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3097                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3098                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3100                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3101                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3102                 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]);
3103                 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);
3104                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3105                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3106
3107                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3108                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3109                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3110                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3111                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3112                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3113                 break;
3114         }
3115 }
3116
3117 #define SKINFRAME_HASH 1024
3118
3119 typedef struct
3120 {
3121         int loadsequence; // incremented each level change
3122         memexpandablearray_t array;
3123         skinframe_t *hash[SKINFRAME_HASH];
3124 }
3125 r_skinframe_t;
3126 r_skinframe_t r_skinframe;
3127
3128 void R_SkinFrame_PrepareForPurge(void)
3129 {
3130         r_skinframe.loadsequence++;
3131         // wrap it without hitting zero
3132         if (r_skinframe.loadsequence >= 200)
3133                 r_skinframe.loadsequence = 1;
3134 }
3135
3136 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3137 {
3138         if (!skinframe)
3139                 return;
3140         // mark the skinframe as used for the purging code
3141         skinframe->loadsequence = r_skinframe.loadsequence;
3142 }
3143
3144 void R_SkinFrame_Purge(void)
3145 {
3146         int i;
3147         skinframe_t *s;
3148         for (i = 0;i < SKINFRAME_HASH;i++)
3149         {
3150                 for (s = r_skinframe.hash[i];s;s = s->next)
3151                 {
3152                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3153                         {
3154                                 if (s->merged == s->base)
3155                                         s->merged = NULL;
3156                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3157                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3158                                 R_PurgeTexture(s->merged);s->merged = NULL;
3159                                 R_PurgeTexture(s->base  );s->base   = NULL;
3160                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3161                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3162                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3163                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3164                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3165                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3166                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3167                                 s->loadsequence = 0;
3168                         }
3169                 }
3170         }
3171 }
3172
3173 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3174         skinframe_t *item;
3175         char basename[MAX_QPATH];
3176
3177         Image_StripImageExtension(name, basename, sizeof(basename));
3178
3179         if( last == NULL ) {
3180                 int hashindex;
3181                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3182                 item = r_skinframe.hash[hashindex];
3183         } else {
3184                 item = last->next;
3185         }
3186
3187         // linearly search through the hash bucket
3188         for( ; item ; item = item->next ) {
3189                 if( !strcmp( item->basename, basename ) ) {
3190                         return item;
3191                 }
3192         }
3193         return NULL;
3194 }
3195
3196 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3197 {
3198         skinframe_t *item;
3199         int hashindex;
3200         char basename[MAX_QPATH];
3201
3202         Image_StripImageExtension(name, basename, sizeof(basename));
3203
3204         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3205         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3206                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3207                         break;
3208
3209         if (!item) {
3210                 rtexture_t *dyntexture;
3211                 // check whether its a dynamic texture
3212                 dyntexture = CL_GetDynTexture( basename );
3213                 if (!add && !dyntexture)
3214                         return NULL;
3215                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3216                 memset(item, 0, sizeof(*item));
3217                 strlcpy(item->basename, basename, sizeof(item->basename));
3218                 item->base = dyntexture; // either NULL or dyntexture handle
3219                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3220                 item->comparewidth = comparewidth;
3221                 item->compareheight = compareheight;
3222                 item->comparecrc = comparecrc;
3223                 item->next = r_skinframe.hash[hashindex];
3224                 r_skinframe.hash[hashindex] = item;
3225         }
3226         else if (textureflags & TEXF_FORCE_RELOAD)
3227         {
3228                 rtexture_t *dyntexture;
3229                 // check whether its a dynamic texture
3230                 dyntexture = CL_GetDynTexture( basename );
3231                 if (!add && !dyntexture)
3232                         return NULL;
3233                 if (item->merged == item->base)
3234                         item->merged = NULL;
3235                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3236                 R_PurgeTexture(item->stain );item->stain  = NULL;
3237                 R_PurgeTexture(item->merged);item->merged = NULL;
3238                 R_PurgeTexture(item->base  );item->base   = NULL;
3239                 R_PurgeTexture(item->pants );item->pants  = NULL;
3240                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3241                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3242                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3243                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3244                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3245         R_PurgeTexture(item->reflect);item->reflect = NULL;
3246                 item->loadsequence = 0;
3247         }
3248         else if( item->base == NULL )
3249         {
3250                 rtexture_t *dyntexture;
3251                 // check whether its a dynamic texture
3252                 // 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]
3253                 dyntexture = CL_GetDynTexture( basename );
3254                 item->base = dyntexture; // either NULL or dyntexture handle
3255         }
3256
3257         R_SkinFrame_MarkUsed(item);
3258         return item;
3259 }
3260
3261 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3262         { \
3263                 unsigned long long avgcolor[5], wsum; \
3264                 int pix, comp, w; \
3265                 avgcolor[0] = 0; \
3266                 avgcolor[1] = 0; \
3267                 avgcolor[2] = 0; \
3268                 avgcolor[3] = 0; \
3269                 avgcolor[4] = 0; \
3270                 wsum = 0; \
3271                 for(pix = 0; pix < cnt; ++pix) \
3272                 { \
3273                         w = 0; \
3274                         for(comp = 0; comp < 3; ++comp) \
3275                                 w += getpixel; \
3276                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3277                         { \
3278                                 ++wsum; \
3279                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3280                                 w = getpixel; \
3281                                 for(comp = 0; comp < 3; ++comp) \
3282                                         avgcolor[comp] += getpixel * w; \
3283                                 avgcolor[3] += w; \
3284                         } \
3285                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3286                         avgcolor[4] += getpixel; \
3287                 } \
3288                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3289                         avgcolor[3] = 1; \
3290                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3291                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3292                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3293                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3294         }
3295
3296 extern cvar_t gl_picmip;
3297 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3298 {
3299         int j;
3300         unsigned char *pixels;
3301         unsigned char *bumppixels;
3302         unsigned char *basepixels = NULL;
3303         int basepixels_width = 0;
3304         int basepixels_height = 0;
3305         skinframe_t *skinframe;
3306         rtexture_t *ddsbase = NULL;
3307         qboolean ddshasalpha = false;
3308         float ddsavgcolor[4];
3309         char basename[MAX_QPATH];
3310         int miplevel = R_PicmipForFlags(textureflags);
3311         int savemiplevel = miplevel;
3312         int mymiplevel;
3313
3314         if (cls.state == ca_dedicated)
3315                 return NULL;
3316
3317         // return an existing skinframe if already loaded
3318         // if loading of the first image fails, don't make a new skinframe as it
3319         // would cause all future lookups of this to be missing
3320         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3321         if (skinframe && skinframe->base)
3322                 return skinframe;
3323
3324         Image_StripImageExtension(name, basename, sizeof(basename));
3325
3326         // check for DDS texture file first
3327         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3328         {
3329                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3330                 if (basepixels == NULL)
3331                         return NULL;
3332         }
3333
3334         // FIXME handle miplevel
3335
3336         if (developer_loading.integer)
3337                 Con_Printf("loading skin \"%s\"\n", name);
3338
3339         // we've got some pixels to store, so really allocate this new texture now
3340         if (!skinframe)
3341                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3342         textureflags &= ~TEXF_FORCE_RELOAD;
3343         skinframe->stain = NULL;
3344         skinframe->merged = NULL;
3345         skinframe->base = NULL;
3346         skinframe->pants = NULL;
3347         skinframe->shirt = NULL;
3348         skinframe->nmap = NULL;
3349         skinframe->gloss = NULL;
3350         skinframe->glow = NULL;
3351         skinframe->fog = NULL;
3352         skinframe->reflect = NULL;
3353         skinframe->hasalpha = false;
3354
3355         if (ddsbase)
3356         {
3357                 skinframe->base = ddsbase;
3358                 skinframe->hasalpha = ddshasalpha;
3359                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3360                 if (r_loadfog && skinframe->hasalpha)
3361                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3362                 //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]);
3363         }
3364         else
3365         {
3366                 basepixels_width = image_width;
3367                 basepixels_height = image_height;
3368                 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);
3369                 if (textureflags & TEXF_ALPHA)
3370                 {
3371                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3372                         {
3373                                 if (basepixels[j] < 255)
3374                                 {
3375                                         skinframe->hasalpha = true;
3376                                         break;
3377                                 }
3378                         }
3379                         if (r_loadfog && skinframe->hasalpha)
3380                         {
3381                                 // has transparent pixels
3382                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3383                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3384                                 {
3385                                         pixels[j+0] = 255;
3386                                         pixels[j+1] = 255;
3387                                         pixels[j+2] = 255;
3388                                         pixels[j+3] = basepixels[j+3];
3389                                 }
3390                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3391                                 Mem_Free(pixels);
3392                         }
3393                 }
3394                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3395 #ifndef USE_GLES2
3396                 //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]);
3397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3398                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3400                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401 #endif
3402         }
3403
3404         if (r_loaddds)
3405         {
3406                 mymiplevel = savemiplevel;
3407                 if (r_loadnormalmap)
3408                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3409                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3410                 if (r_loadgloss)
3411                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3412                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3414                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3415         }
3416
3417         // _norm is the name used by tenebrae and has been adopted as standard
3418         if (r_loadnormalmap && skinframe->nmap == NULL)
3419         {
3420                 mymiplevel = savemiplevel;
3421                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3422                 {
3423                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3424                         Mem_Free(pixels);
3425                         pixels = NULL;
3426                 }
3427                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3428                 {
3429                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3430                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3431                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3432                         Mem_Free(pixels);
3433                         Mem_Free(bumppixels);
3434                 }
3435                 else if (r_shadow_bumpscale_basetexture.value > 0)
3436                 {
3437                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3438                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3439                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%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);
3440                         Mem_Free(pixels);
3441                 }
3442 #ifndef USE_GLES2
3443                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3444                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3445 #endif
3446         }
3447
3448         // _luma is supported only for tenebrae compatibility
3449         // _glow is the preferred name
3450         mymiplevel = savemiplevel;
3451         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3452         {
3453                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%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);
3454 #ifndef USE_GLES2
3455                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3456                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3457 #endif
3458                 Mem_Free(pixels);pixels = NULL;
3459         }
3460
3461         mymiplevel = savemiplevel;
3462         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%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);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3467                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3468 #endif
3469                 Mem_Free(pixels);
3470                 pixels = NULL;
3471         }
3472
3473         mymiplevel = savemiplevel;
3474         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%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);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3479                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3480 #endif
3481                 Mem_Free(pixels);
3482                 pixels = NULL;
3483         }
3484
3485         mymiplevel = savemiplevel;
3486         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3487         {
3488                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%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);
3489 #ifndef USE_GLES2
3490                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3491                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3492 #endif
3493                 Mem_Free(pixels);
3494                 pixels = NULL;
3495         }
3496
3497         mymiplevel = savemiplevel;
3498         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3499         {
3500                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%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);
3501 #ifndef USE_GLES2
3502                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3503                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3504 #endif
3505                 Mem_Free(pixels);
3506                 pixels = NULL;
3507         }
3508
3509         if (basepixels)
3510                 Mem_Free(basepixels);
3511
3512         return skinframe;
3513 }
3514
3515 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3516 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3517 {
3518         int i;
3519         unsigned char *temp1, *temp2;
3520         skinframe_t *skinframe;
3521
3522         if (cls.state == ca_dedicated)
3523                 return NULL;
3524
3525         // if already loaded just return it, otherwise make a new skinframe
3526         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3527         if (skinframe && skinframe->base)
3528                 return skinframe;
3529         textureflags &= ~TEXF_FORCE_RELOAD;
3530
3531         skinframe->stain = NULL;
3532         skinframe->merged = NULL;
3533         skinframe->base = NULL;
3534         skinframe->pants = NULL;
3535         skinframe->shirt = NULL;
3536         skinframe->nmap = NULL;
3537         skinframe->gloss = NULL;
3538         skinframe->glow = NULL;
3539         skinframe->fog = NULL;
3540         skinframe->reflect = NULL;
3541         skinframe->hasalpha = false;
3542
3543         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3544         if (!skindata)
3545                 return NULL;
3546
3547         if (developer_loading.integer)
3548                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3549
3550         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3551         {
3552                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3553                 temp2 = temp1 + width * height * 4;
3554                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3555                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3556                 Mem_Free(temp1);
3557         }
3558         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3559         if (textureflags & TEXF_ALPHA)
3560         {
3561                 for (i = 3;i < width * height * 4;i += 4)
3562                 {
3563                         if (skindata[i] < 255)
3564                         {
3565                                 skinframe->hasalpha = true;
3566                                 break;
3567                         }
3568                 }
3569                 if (r_loadfog && skinframe->hasalpha)
3570                 {
3571                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3572                         memcpy(fogpixels, skindata, width * height * 4);
3573                         for (i = 0;i < width * height * 4;i += 4)
3574                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3575                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3576                         Mem_Free(fogpixels);
3577                 }
3578         }
3579
3580         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3581         //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]);
3582
3583         return skinframe;
3584 }
3585
3586 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3587 {
3588         int i;
3589         int featuresmask;
3590         skinframe_t *skinframe;
3591
3592         if (cls.state == ca_dedicated)
3593                 return NULL;
3594
3595         // if already loaded just return it, otherwise make a new skinframe
3596         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3597         if (skinframe && skinframe->base)
3598                 return skinframe;
3599         textureflags &= ~TEXF_FORCE_RELOAD;
3600
3601         skinframe->stain = NULL;
3602         skinframe->merged = NULL;
3603         skinframe->base = NULL;
3604         skinframe->pants = NULL;
3605         skinframe->shirt = NULL;
3606         skinframe->nmap = NULL;
3607         skinframe->gloss = NULL;
3608         skinframe->glow = NULL;
3609         skinframe->fog = NULL;
3610         skinframe->reflect = NULL;
3611         skinframe->hasalpha = false;
3612
3613         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3614         if (!skindata)
3615                 return NULL;
3616
3617         if (developer_loading.integer)
3618                 Con_Printf("loading quake skin \"%s\"\n", name);
3619
3620         // 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)
3621         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3622         memcpy(skinframe->qpixels, skindata, width*height);
3623         skinframe->qwidth = width;
3624         skinframe->qheight = height;
3625
3626         featuresmask = 0;
3627         for (i = 0;i < width * height;i++)
3628                 featuresmask |= palette_featureflags[skindata[i]];
3629
3630         skinframe->hasalpha = false;
3631         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3632         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3633         skinframe->qgeneratemerged = true;
3634         skinframe->qgeneratebase = skinframe->qhascolormapping;
3635         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3636
3637         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3638         //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]);
3639
3640         return skinframe;
3641 }
3642
3643 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3644 {
3645         int width;
3646         int height;
3647         unsigned char *skindata;
3648
3649         if (!skinframe->qpixels)
3650                 return;
3651
3652         if (!skinframe->qhascolormapping)
3653                 colormapped = false;
3654
3655         if (colormapped)
3656         {
3657                 if (!skinframe->qgeneratebase)
3658                         return;
3659         }
3660         else
3661         {
3662                 if (!skinframe->qgeneratemerged)
3663                         return;
3664         }
3665
3666         width = skinframe->qwidth;
3667         height = skinframe->qheight;
3668         skindata = skinframe->qpixels;
3669
3670         if (skinframe->qgeneratenmap)
3671         {
3672                 unsigned char *temp1, *temp2;
3673                 skinframe->qgeneratenmap = false;
3674                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3675                 temp2 = temp1 + width * height * 4;
3676                 // use either a custom palette or the quake palette
3677                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3678                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3679                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3680                 Mem_Free(temp1);
3681         }
3682
3683         if (skinframe->qgenerateglow)
3684         {
3685                 skinframe->qgenerateglow = false;
3686                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3687         }
3688
3689         if (colormapped)
3690         {
3691                 skinframe->qgeneratebase = false;
3692                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%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);
3693                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3694                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3695         }
3696         else
3697         {
3698                 skinframe->qgeneratemerged = false;
3699                 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);
3700         }
3701
3702         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3703         {
3704                 Mem_Free(skinframe->qpixels);
3705                 skinframe->qpixels = NULL;
3706         }
3707 }
3708
3709 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)
3710 {
3711         int i;
3712         skinframe_t *skinframe;
3713
3714         if (cls.state == ca_dedicated)
3715                 return NULL;
3716
3717         // if already loaded just return it, otherwise make a new skinframe
3718         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3719         if (skinframe && skinframe->base)
3720                 return skinframe;
3721         textureflags &= ~TEXF_FORCE_RELOAD;
3722
3723         skinframe->stain = NULL;
3724         skinframe->merged = NULL;
3725         skinframe->base = NULL;
3726         skinframe->pants = NULL;
3727         skinframe->shirt = NULL;
3728         skinframe->nmap = NULL;
3729         skinframe->gloss = NULL;
3730         skinframe->glow = NULL;
3731         skinframe->fog = NULL;
3732         skinframe->reflect = NULL;
3733         skinframe->hasalpha = false;
3734
3735         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3736         if (!skindata)
3737                 return NULL;
3738
3739         if (developer_loading.integer)
3740                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3741
3742         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3743         if (textureflags & TEXF_ALPHA)
3744         {
3745                 for (i = 0;i < width * height;i++)
3746                 {
3747                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3748                         {
3749                                 skinframe->hasalpha = true;
3750                                 break;
3751                         }
3752                 }
3753                 if (r_loadfog && skinframe->hasalpha)
3754                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3755         }
3756
3757         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3758         //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]);
3759
3760         return skinframe;
3761 }
3762
3763 skinframe_t *R_SkinFrame_LoadMissing(void)
3764 {
3765         skinframe_t *skinframe;
3766
3767         if (cls.state == ca_dedicated)
3768                 return NULL;
3769
3770         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3771         skinframe->stain = NULL;
3772         skinframe->merged = NULL;
3773         skinframe->base = NULL;
3774         skinframe->pants = NULL;
3775         skinframe->shirt = NULL;
3776         skinframe->nmap = NULL;
3777         skinframe->gloss = NULL;
3778         skinframe->glow = NULL;
3779         skinframe->fog = NULL;
3780         skinframe->reflect = NULL;
3781         skinframe->hasalpha = false;
3782
3783         skinframe->avgcolor[0] = rand() / RAND_MAX;
3784         skinframe->avgcolor[1] = rand() / RAND_MAX;
3785         skinframe->avgcolor[2] = rand() / RAND_MAX;
3786         skinframe->avgcolor[3] = 1;
3787
3788         return skinframe;
3789 }
3790
3791 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3792 typedef struct suffixinfo_s
3793 {
3794         const char *suffix;
3795         qboolean flipx, flipy, flipdiagonal;
3796 }
3797 suffixinfo_t;
3798 static suffixinfo_t suffix[3][6] =
3799 {
3800         {
3801                 {"px",   false, false, false},
3802                 {"nx",   false, false, false},
3803                 {"py",   false, false, false},
3804                 {"ny",   false, false, false},
3805                 {"pz",   false, false, false},
3806                 {"nz",   false, false, false}
3807         },
3808         {
3809                 {"posx", false, false, false},
3810                 {"negx", false, false, false},
3811                 {"posy", false, false, false},
3812                 {"negy", false, false, false},
3813                 {"posz", false, false, false},
3814                 {"negz", false, false, false}
3815         },
3816         {
3817                 {"rt",    true, false,  true},
3818                 {"lf",   false,  true,  true},
3819                 {"ft",    true,  true, false},
3820                 {"bk",   false, false, false},
3821                 {"up",    true, false,  true},
3822                 {"dn",    true, false,  true}
3823         }
3824 };
3825
3826 static int componentorder[4] = {0, 1, 2, 3};
3827
3828 rtexture_t *R_LoadCubemap(const char *basename)
3829 {
3830         int i, j, cubemapsize;
3831         unsigned char *cubemappixels, *image_buffer;
3832         rtexture_t *cubemaptexture;
3833         char name[256];
3834         // must start 0 so the first loadimagepixels has no requested width/height
3835         cubemapsize = 0;
3836         cubemappixels = NULL;
3837         cubemaptexture = NULL;
3838         // keep trying different suffix groups (posx, px, rt) until one loads
3839         for (j = 0;j < 3 && !cubemappixels;j++)
3840         {
3841                 // load the 6 images in the suffix group
3842                 for (i = 0;i < 6;i++)
3843                 {
3844                         // generate an image name based on the base and and suffix
3845                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3846                         // load it
3847                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3848                         {
3849                                 // an image loaded, make sure width and height are equal
3850                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3851                                 {
3852                                         // if this is the first image to load successfully, allocate the cubemap memory
3853                                         if (!cubemappixels && image_width >= 1)
3854                                         {
3855                                                 cubemapsize = image_width;
3856                                                 // note this clears to black, so unavailable sides are black
3857                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3858                                         }
3859                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3860                                         if (cubemappixels)
3861                                                 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);
3862                                 }
3863                                 else
3864                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3865                                 // free the image
3866                                 Mem_Free(image_buffer);
3867                         }
3868                 }
3869         }
3870         // if a cubemap loaded, upload it
3871         if (cubemappixels)
3872         {
3873                 if (developer_loading.integer)
3874                         Con_Printf("loading cubemap \"%s\"\n", basename);
3875
3876                 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);
3877                 Mem_Free(cubemappixels);
3878         }
3879         else
3880         {
3881                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3882                 if (developer_loading.integer)
3883                 {
3884                         Con_Printf("(tried tried images ");
3885                         for (j = 0;j < 3;j++)
3886                                 for (i = 0;i < 6;i++)
3887                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3888                         Con_Print(" and was unable to find any of them).\n");
3889                 }
3890         }
3891         return cubemaptexture;
3892 }
3893
3894 rtexture_t *R_GetCubemap(const char *basename)
3895 {
3896         int i;
3897         for (i = 0;i < r_texture_numcubemaps;i++)
3898                 if (r_texture_cubemaps[i] != NULL)
3899                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3900                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3901         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3902                 return r_texture_whitecube;
3903         r_texture_numcubemaps++;
3904         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3905         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3906         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3907         return r_texture_cubemaps[i]->texture;
3908 }
3909
3910 void R_FreeCubemap(const char *basename)
3911 {
3912         int i;
3913
3914         for (i = 0;i < r_texture_numcubemaps;i++)
3915         {
3916                 if (r_texture_cubemaps[i] != NULL)
3917                 {
3918                         if (r_texture_cubemaps[i]->texture)
3919                         {
3920                                 if (developer_loading.integer)
3921                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3922                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3923                                 Mem_Free(r_texture_cubemaps[i]);
3924                                 r_texture_cubemaps[i] = NULL;
3925                         }
3926                 }
3927         }
3928 }
3929
3930 void R_FreeCubemaps(void)
3931 {
3932         int i;
3933         for (i = 0;i < r_texture_numcubemaps;i++)
3934         {
3935                 if (developer_loading.integer)
3936                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3937                 if (r_texture_cubemaps[i] != NULL)
3938                 {
3939                         if (r_texture_cubemaps[i]->texture)
3940                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3941                         Mem_Free(r_texture_cubemaps[i]);
3942                 }
3943         }
3944         r_texture_numcubemaps = 0;
3945 }
3946
3947 void R_Main_FreeViewCache(void)
3948 {
3949         if (r_refdef.viewcache.entityvisible)
3950                 Mem_Free(r_refdef.viewcache.entityvisible);
3951         if (r_refdef.viewcache.world_pvsbits)
3952                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3953         if (r_refdef.viewcache.world_leafvisible)
3954                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3955         if (r_refdef.viewcache.world_surfacevisible)
3956                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3957         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3958 }
3959
3960 void R_Main_ResizeViewCache(void)
3961 {
3962         int numentities = r_refdef.scene.numentities;
3963         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3964         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3965         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3966         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3967         if (r_refdef.viewcache.maxentities < numentities)
3968         {
3969                 r_refdef.viewcache.maxentities = numentities;
3970                 if (r_refdef.viewcache.entityvisible)
3971                         Mem_Free(r_refdef.viewcache.entityvisible);
3972                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3973         }
3974         if (r_refdef.viewcache.world_numclusters != numclusters)
3975         {
3976                 r_refdef.viewcache.world_numclusters = numclusters;
3977                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3978                 if (r_refdef.viewcache.world_pvsbits)
3979                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3980                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3981         }
3982         if (r_refdef.viewcache.world_numleafs != numleafs)
3983         {
3984                 r_refdef.viewcache.world_numleafs = numleafs;
3985                 if (r_refdef.viewcache.world_leafvisible)
3986                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3987                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3988         }
3989         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3990         {
3991                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3992                 if (r_refdef.viewcache.world_surfacevisible)
3993                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3994                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3995         }
3996 }
3997
3998 extern rtexture_t *loadingscreentexture;
3999 void gl_main_start(void)
4000 {
4001         loadingscreentexture = NULL;
4002         r_texture_blanknormalmap = NULL;
4003         r_texture_white = NULL;
4004         r_texture_grey128 = NULL;
4005         r_texture_black = NULL;
4006         r_texture_whitecube = NULL;
4007         r_texture_normalizationcube = NULL;
4008         r_texture_fogattenuation = NULL;
4009         r_texture_fogheighttexture = NULL;
4010         r_texture_gammaramps = NULL;
4011         r_texture_numcubemaps = 0;
4012
4013         r_loaddds = r_texture_dds_load.integer != 0;
4014         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4015
4016         switch(vid.renderpath)
4017         {
4018         case RENDERPATH_GL20:
4019         case RENDERPATH_D3D9:
4020         case RENDERPATH_D3D10:
4021         case RENDERPATH_D3D11:
4022         case RENDERPATH_SOFT:
4023         case RENDERPATH_GLES2:
4024                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025                 Cvar_SetValueQuick(&gl_combine, 1);
4026                 Cvar_SetValueQuick(&r_glsl, 1);
4027                 r_loadnormalmap = true;
4028                 r_loadgloss = true;
4029                 r_loadfog = false;
4030                 break;
4031         case RENDERPATH_GL13:
4032         case RENDERPATH_GLES1:
4033                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4034                 Cvar_SetValueQuick(&gl_combine, 1);
4035                 Cvar_SetValueQuick(&r_glsl, 0);
4036                 r_loadnormalmap = false;
4037                 r_loadgloss = false;
4038                 r_loadfog = true;
4039                 break;
4040         case RENDERPATH_GL11:
4041                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4042                 Cvar_SetValueQuick(&gl_combine, 0);
4043                 Cvar_SetValueQuick(&r_glsl, 0);
4044                 r_loadnormalmap = false;
4045                 r_loadgloss = false;
4046                 r_loadfog = true;
4047                 break;
4048         }
4049
4050         R_AnimCache_Free();
4051         R_FrameData_Reset();
4052
4053         r_numqueries = 0;
4054         r_maxqueries = 0;
4055         memset(r_queries, 0, sizeof(r_queries));
4056
4057         r_qwskincache = NULL;
4058         r_qwskincache_size = 0;
4059
4060         // due to caching of texture_t references, the collision cache must be reset
4061         Collision_Cache_Reset(true);
4062
4063         // set up r_skinframe loading system for textures
4064         memset(&r_skinframe, 0, sizeof(r_skinframe));
4065         r_skinframe.loadsequence = 1;
4066         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4067
4068         r_main_texturepool = R_AllocTexturePool();
4069         R_BuildBlankTextures();
4070         R_BuildNoTexture();
4071         if (vid.support.arb_texture_cube_map)
4072         {
4073                 R_BuildWhiteCube();
4074                 R_BuildNormalizationCube();
4075         }
4076         r_texture_fogattenuation = NULL;
4077         r_texture_fogheighttexture = NULL;
4078         r_texture_gammaramps = NULL;
4079         //r_texture_fogintensity = NULL;
4080         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4081         memset(&r_waterstate, 0, sizeof(r_waterstate));
4082         r_glsl_permutation = NULL;
4083         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4084         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4085         glslshaderstring = NULL;
4086 #ifdef SUPPORTD3D
4087         r_hlsl_permutation = NULL;
4088         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4089         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4090 #endif
4091         hlslshaderstring = NULL;
4092         memset(&r_svbsp, 0, sizeof (r_svbsp));
4093
4094         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4095         r_texture_numcubemaps = 0;
4096
4097         r_refdef.fogmasktable_density = 0;
4098 }
4099
4100 void gl_main_shutdown(void)
4101 {
4102         R_AnimCache_Free();
4103         R_FrameData_Reset();
4104
4105         R_Main_FreeViewCache();
4106
4107         switch(vid.renderpath)
4108         {
4109         case RENDERPATH_GL11:
4110         case RENDERPATH_GL13:
4111         case RENDERPATH_GL20:
4112         case RENDERPATH_GLES1:
4113         case RENDERPATH_GLES2:
4114 #ifdef GL_SAMPLES_PASSED_ARB
4115                 if (r_maxqueries)
4116                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4117 #endif
4118                 break;
4119         case RENDERPATH_D3D9:
4120                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4121                 break;
4122         case RENDERPATH_D3D10:
4123                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4124                 break;
4125         case RENDERPATH_D3D11:
4126                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4127                 break;
4128         case RENDERPATH_SOFT:
4129                 break;
4130         }
4131
4132         r_numqueries = 0;
4133         r_maxqueries = 0;
4134         memset(r_queries, 0, sizeof(r_queries));
4135
4136         r_qwskincache = NULL;
4137         r_qwskincache_size = 0;
4138
4139         // clear out the r_skinframe state
4140         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4141         memset(&r_skinframe, 0, sizeof(r_skinframe));
4142
4143         if (r_svbsp.nodes)
4144                 Mem_Free(r_svbsp.nodes);
4145         memset(&r_svbsp, 0, sizeof (r_svbsp));
4146         R_FreeTexturePool(&r_main_texturepool);
4147         loadingscreentexture = NULL;
4148         r_texture_blanknormalmap = NULL;
4149         r_texture_white = NULL;
4150         r_texture_grey128 = NULL;
4151         r_texture_black = NULL;
4152         r_texture_whitecube = NULL;
4153         r_texture_normalizationcube = NULL;
4154         r_texture_fogattenuation = NULL;
4155         r_texture_fogheighttexture = NULL;
4156         r_texture_gammaramps = NULL;
4157         r_texture_numcubemaps = 0;
4158         //r_texture_fogintensity = NULL;
4159         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4160         memset(&r_waterstate, 0, sizeof(r_waterstate));
4161         R_GLSL_Restart_f();
4162
4163         r_glsl_permutation = NULL;
4164         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4165         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4166         glslshaderstring = NULL;
4167 #ifdef SUPPORTD3D
4168         r_hlsl_permutation = NULL;
4169         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4170         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4171 #endif
4172         hlslshaderstring = NULL;
4173 }
4174
4175 extern void CL_ParseEntityLump(char *entitystring);
4176 void gl_main_newmap(void)
4177 {
4178         // FIXME: move this code to client
4179         char *entities, entname[MAX_QPATH];
4180         if (r_qwskincache)
4181                 Mem_Free(r_qwskincache);
4182         r_qwskincache = NULL;
4183         r_qwskincache_size = 0;
4184         if (cl.worldmodel)
4185         {
4186                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4187                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4188                 {
4189                         CL_ParseEntityLump(entities);
4190                         Mem_Free(entities);
4191                         return;
4192                 }
4193                 if (cl.worldmodel->brush.entities)
4194                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4195         }
4196         R_Main_FreeViewCache();
4197
4198         R_FrameData_Reset();
4199 }
4200
4201 void GL_Main_Init(void)
4202 {
4203         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4204
4205         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4206         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4207         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4208         if (gamemode == GAME_NEHAHRA)
4209         {
4210                 Cvar_RegisterVariable (&gl_fogenable);
4211                 Cvar_RegisterVariable (&gl_fogdensity);
4212                 Cvar_RegisterVariable (&gl_fogred);
4213                 Cvar_RegisterVariable (&gl_foggreen);
4214                 Cvar_RegisterVariable (&gl_fogblue);
4215                 Cvar_RegisterVariable (&gl_fogstart);
4216                 Cvar_RegisterVariable (&gl_fogend);
4217                 Cvar_RegisterVariable (&gl_skyclip);
4218         }
4219         Cvar_RegisterVariable(&r_motionblur);
4220         Cvar_RegisterVariable(&r_damageblur);
4221         Cvar_RegisterVariable(&r_motionblur_averaging);
4222         Cvar_RegisterVariable(&r_motionblur_randomize);
4223         Cvar_RegisterVariable(&r_motionblur_minblur);
4224         Cvar_RegisterVariable(&r_motionblur_maxblur);
4225         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4226         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4227         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4228         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4229         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4230         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4231         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4232         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4233         Cvar_RegisterVariable(&r_equalize_entities_by);
4234         Cvar_RegisterVariable(&r_equalize_entities_to);
4235         Cvar_RegisterVariable(&r_depthfirst);
4236         Cvar_RegisterVariable(&r_useinfinitefarclip);
4237         Cvar_RegisterVariable(&r_farclip_base);
4238         Cvar_RegisterVariable(&r_farclip_world);
4239         Cvar_RegisterVariable(&r_nearclip);
4240         Cvar_RegisterVariable(&r_deformvertexes);
4241         Cvar_RegisterVariable(&r_transparent);
4242         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4243         Cvar_RegisterVariable(&r_showoverdraw);
4244         Cvar_RegisterVariable(&r_showbboxes);
4245         Cvar_RegisterVariable(&r_showsurfaces);
4246         Cvar_RegisterVariable(&r_showtris);
4247         Cvar_RegisterVariable(&r_shownormals);
4248         Cvar_RegisterVariable(&r_showlighting);
4249         Cvar_RegisterVariable(&r_showshadowvolumes);
4250         Cvar_RegisterVariable(&r_showcollisionbrushes);
4251         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4252         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4253         Cvar_RegisterVariable(&r_showdisabledepthtest);
4254         Cvar_RegisterVariable(&r_drawportals);
4255         Cvar_RegisterVariable(&r_drawentities);
4256         Cvar_RegisterVariable(&r_draw2d);
4257         Cvar_RegisterVariable(&r_drawworld);
4258         Cvar_RegisterVariable(&r_cullentities_trace);
4259         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4260         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4261         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4262         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4263         Cvar_RegisterVariable(&r_sortentities);
4264         Cvar_RegisterVariable(&r_drawviewmodel);
4265         Cvar_RegisterVariable(&r_drawexteriormodel);
4266         Cvar_RegisterVariable(&r_speeds);
4267         Cvar_RegisterVariable(&r_fullbrights);
4268         Cvar_RegisterVariable(&r_wateralpha);
4269         Cvar_RegisterVariable(&r_dynamic);
4270         Cvar_RegisterVariable(&r_fakelight);
4271         Cvar_RegisterVariable(&r_fakelight_intensity);
4272         Cvar_RegisterVariable(&r_fullbright);
4273         Cvar_RegisterVariable(&r_shadows);
4274         Cvar_RegisterVariable(&r_shadows_darken);
4275         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4276         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4277         Cvar_RegisterVariable(&r_shadows_throwdistance);
4278         Cvar_RegisterVariable(&r_shadows_throwdirection);
4279         Cvar_RegisterVariable(&r_shadows_focus);
4280         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4281         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4282         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4283         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4284         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4285         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4286         Cvar_RegisterVariable(&r_fog_exp2);
4287         Cvar_RegisterVariable(&r_fog_clear);
4288         Cvar_RegisterVariable(&r_drawfog);
4289         Cvar_RegisterVariable(&r_transparentdepthmasking);
4290         Cvar_RegisterVariable(&r_transparent_sortmindist);
4291         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4292         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4293         Cvar_RegisterVariable(&r_texture_dds_load);
4294         Cvar_RegisterVariable(&r_texture_dds_save);
4295         Cvar_RegisterVariable(&r_textureunits);
4296         Cvar_RegisterVariable(&gl_combine);
4297         Cvar_RegisterVariable(&r_viewfbo);
4298         Cvar_RegisterVariable(&r_viewscale);
4299         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4302         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4303         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4304         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4305         Cvar_RegisterVariable(&r_glsl);
4306         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4307         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4312         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4313         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4314         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4315         Cvar_RegisterVariable(&r_glsl_postprocess);
4316         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4321         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4322         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4323         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4324
4325         Cvar_RegisterVariable(&r_water);
4326         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4327         Cvar_RegisterVariable(&r_water_clippingplanebias);
4328         Cvar_RegisterVariable(&r_water_refractdistort);
4329         Cvar_RegisterVariable(&r_water_reflectdistort);
4330         Cvar_RegisterVariable(&r_water_scissormode);
4331         Cvar_RegisterVariable(&r_water_lowquality);
4332
4333         Cvar_RegisterVariable(&r_lerpsprites);
4334         Cvar_RegisterVariable(&r_lerpmodels);
4335         Cvar_RegisterVariable(&r_lerplightstyles);
4336         Cvar_RegisterVariable(&r_waterscroll);
4337         Cvar_RegisterVariable(&r_bloom);
4338         Cvar_RegisterVariable(&r_bloom_colorscale);
4339         Cvar_RegisterVariable(&r_bloom_brighten);
4340         Cvar_RegisterVariable(&r_bloom_blur);
4341         Cvar_RegisterVariable(&r_bloom_resolution);
4342         Cvar_RegisterVariable(&r_bloom_colorexponent);
4343         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4344         Cvar_RegisterVariable(&r_hdr);
4345         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4346         Cvar_RegisterVariable(&r_hdr_glowintensity);
4347         Cvar_RegisterVariable(&r_hdr_range);
4348         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4349         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4350         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4351         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4352         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4353         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4354         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4355         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4356         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4357         Cvar_RegisterVariable(&developer_texturelogging);
4358         Cvar_RegisterVariable(&gl_lightmaps);
4359         Cvar_RegisterVariable(&r_test);
4360         Cvar_RegisterVariable(&r_glsl_saturation);
4361         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4362         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4363         Cvar_RegisterVariable(&r_framedatasize);
4364         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4365                 Cvar_SetValue("r_fullbrights", 0);
4366         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4367 }
4368
4369 extern void R_Textures_Init(void);
4370 extern void GL_Draw_Init(void);
4371 extern void GL_Main_Init(void);
4372 extern void R_Shadow_Init(void);
4373 extern void R_Sky_Init(void);
4374 extern void GL_Surf_Init(void);
4375 extern void R_Particles_Init(void);
4376 extern void R_Explosion_Init(void);
4377 extern void gl_backend_init(void);
4378 extern void Sbar_Init(void);
4379 extern void R_LightningBeams_Init(void);
4380 extern void Mod_RenderInit(void);
4381 extern void Font_Init(void);
4382
4383 void Render_Init(void)
4384 {
4385         gl_backend_init();
4386         R_Textures_Init();
4387         GL_Main_Init();
4388         Font_Init();
4389         GL_Draw_Init();
4390         R_Shadow_Init();
4391         R_Sky_Init();
4392         GL_Surf_Init();
4393         Sbar_Init();
4394         R_Particles_Init();
4395         R_Explosion_Init();
4396         R_LightningBeams_Init();
4397         Mod_RenderInit();
4398 }
4399
4400 /*
4401 ===============
4402 GL_Init
4403 ===============
4404 */
4405 #ifndef USE_GLES2
4406 extern char *ENGINE_EXTENSIONS;
4407 void GL_Init (void)
4408 {
4409         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4410         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4411         gl_version = (const char *)qglGetString(GL_VERSION);
4412         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4413
4414         if (!gl_extensions)
4415                 gl_extensions = "";
4416         if (!gl_platformextensions)
4417                 gl_platformextensions = "";
4418
4419         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4420         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4421         Con_Printf("GL_VERSION: %s\n", gl_version);
4422         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4423         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4424
4425         VID_CheckExtensions();
4426
4427         // LordHavoc: report supported extensions
4428         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4429
4430         // clear to black (loading plaque will be seen over this)
4431         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4432 }
4433 #endif
4434
4435 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4436 {
4437         int i;
4438         mplane_t *p;
4439         if (r_trippy.integer)
4440                 return false;
4441         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4442         {
4443                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4444                 if (i == 4)
4445                         continue;
4446                 p = r_refdef.view.frustum + i;
4447                 switch(p->signbits)
4448                 {
4449                 default:
4450                 case 0:
4451                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 1:
4455                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 case 2:
4459                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4460                                 return true;
4461                         break;
4462                 case 3:
4463                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4464                                 return true;
4465                         break;
4466                 case 4:
4467                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4468                                 return true;
4469                         break;
4470                 case 5:
4471                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 6:
4475                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 7:
4479                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 }
4483         }
4484         return false;
4485 }
4486
4487 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4488 {
4489         int i;
4490         const mplane_t *p;
4491         if (r_trippy.integer)
4492                 return false;
4493         for (i = 0;i < numplanes;i++)
4494         {
4495                 p = planes + i;
4496                 switch(p->signbits)
4497                 {
4498                 default:
4499                 case 0:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 1:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 case 2:
4508                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4509                                 return true;
4510                         break;
4511                 case 3:
4512                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4513                                 return true;
4514                         break;
4515                 case 4:
4516                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4517                                 return true;
4518                         break;
4519                 case 5:
4520                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4521                                 return true;
4522                         break;
4523                 case 6:
4524                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4525                                 return true;
4526                         break;
4527                 case 7:
4528                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4529                                 return true;
4530                         break;
4531                 }
4532         }
4533         return false;
4534 }
4535
4536 //==================================================================================
4537
4538 // LordHavoc: this stores temporary data used within the same frame
4539
4540 typedef struct r_framedata_mem_s
4541 {
4542         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4543         size_t size; // how much usable space
4544         size_t current; // how much space in use
4545         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4546         size_t wantedsize; // how much space was allocated
4547         unsigned char *data; // start of real data (16byte aligned)
4548 }
4549 r_framedata_mem_t;
4550
4551 static r_framedata_mem_t *r_framedata_mem;
4552
4553 void R_FrameData_Reset(void)
4554 {
4555         while (r_framedata_mem)
4556         {
4557                 r_framedata_mem_t *next = r_framedata_mem->purge;
4558                 Mem_Free(r_framedata_mem);
4559                 r_framedata_mem = next;
4560         }
4561 }
4562
4563 void R_FrameData_Resize(void)
4564 {
4565         size_t wantedsize;
4566         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4567         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4568         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4569         {
4570                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4571                 newmem->wantedsize = wantedsize;
4572                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4573                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4574                 newmem->current = 0;
4575                 newmem->mark = 0;
4576                 newmem->purge = r_framedata_mem;
4577                 r_framedata_mem = newmem;
4578         }
4579 }
4580
4581 void R_FrameData_NewFrame(void)
4582 {
4583         R_FrameData_Resize();
4584         if (!r_framedata_mem)
4585                 return;
4586         // if we ran out of space on the last frame, free the old memory now
4587         while (r_framedata_mem->purge)
4588         {
4589                 // repeatedly remove the second item in the list, leaving only head
4590                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4591                 Mem_Free(r_framedata_mem->purge);
4592                 r_framedata_mem->purge = next;
4593         }
4594         // reset the current mem pointer
4595         r_framedata_mem->current = 0;
4596         r_framedata_mem->mark = 0;
4597 }
4598
4599 void *R_FrameData_Alloc(size_t size)
4600 {
4601         void *data;
4602
4603         // align to 16 byte boundary - the data pointer is already aligned, so we
4604         // only need to ensure the size of every allocation is also aligned
4605         size = (size + 15) & ~15;
4606
4607         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4608         {
4609                 // emergency - we ran out of space, allocate more memory
4610                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4611                 R_FrameData_Resize();
4612         }
4613
4614         data = r_framedata_mem->data + r_framedata_mem->current;
4615         r_framedata_mem->current += size;
4616
4617         // count the usage for stats
4618         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4619         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4620
4621         return (void *)data;
4622 }
4623
4624 void *R_FrameData_Store(size_t size, void *data)
4625 {
4626         void *d = R_FrameData_Alloc(size);
4627         if (d && data)
4628                 memcpy(d, data, size);
4629         return d;
4630 }
4631
4632 void R_FrameData_SetMark(void)
4633 {
4634         if (!r_framedata_mem)
4635                 return;
4636         r_framedata_mem->mark = r_framedata_mem->current;
4637 }
4638
4639 void R_FrameData_ReturnToMark(void)
4640 {
4641         if (!r_framedata_mem)
4642                 return;
4643         r_framedata_mem->current = r_framedata_mem->mark;
4644 }
4645
4646 //==================================================================================
4647
4648 // LordHavoc: animcache originally written by Echon, rewritten since then
4649
4650 /**
4651  * Animation cache prevents re-generating mesh data for an animated model
4652  * multiple times in one frame for lighting, shadowing, reflections, etc.
4653  */
4654
4655 void R_AnimCache_Free(void)
4656 {
4657 }
4658
4659 void R_AnimCache_ClearCache(void)
4660 {
4661         int i;
4662         entity_render_t *ent;
4663
4664         for (i = 0;i < r_refdef.scene.numentities;i++)
4665         {
4666                 ent = r_refdef.scene.entities[i];
4667                 ent->animcache_vertex3f = NULL;
4668                 ent->animcache_normal3f = NULL;
4669                 ent->animcache_svector3f = NULL;
4670                 ent->animcache_tvector3f = NULL;
4671                 ent->animcache_vertexmesh = NULL;
4672                 ent->animcache_vertex3fbuffer = NULL;
4673                 ent->animcache_vertexmeshbuffer = NULL;
4674         }
4675 }
4676
4677 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4678 {
4679         int i;
4680
4681         // check if we need the meshbuffers
4682         if (!vid.useinterleavedarrays)
4683                 return;
4684
4685         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4686                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4687         // TODO: upload vertex3f buffer?
4688         if (ent->animcache_vertexmesh)
4689         {
4690                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4691                 for (i = 0;i < numvertices;i++)
4692                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4693                 if (ent->animcache_svector3f)
4694                         for (i = 0;i < numvertices;i++)
4695                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4696                 if (ent->animcache_tvector3f)
4697                         for (i = 0;i < numvertices;i++)
4698                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4699                 if (ent->animcache_normal3f)
4700                         for (i = 0;i < numvertices;i++)
4701                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4702                 // TODO: upload vertexmeshbuffer?
4703         }
4704 }
4705
4706 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4707 {
4708         dp_model_t *model = ent->model;
4709         int numvertices;
4710         // see if it's already cached this frame
4711         if (ent->animcache_vertex3f)
4712         {
4713                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4714                 if (wantnormals || wanttangents)
4715                 {
4716                         if (ent->animcache_normal3f)
4717                                 wantnormals = false;
4718                         if (ent->animcache_svector3f)
4719                                 wanttangents = false;
4720                         if (wantnormals || wanttangents)
4721                         {
4722                                 numvertices = model->surfmesh.num_vertices;
4723                                 if (wantnormals)
4724                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                                 if (wanttangents)
4726                                 {
4727                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4728                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4729                                 }
4730                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4731                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4732                         }
4733                 }
4734         }
4735         else
4736         {
4737                 // see if this ent is worth caching
4738                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4739                         return false;
4740                 // get some memory for this entity and generate mesh data
4741                 numvertices = model->surfmesh.num_vertices;
4742                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4743                 if (wantnormals)
4744                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4745                 if (wanttangents)
4746                 {
4747                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4748                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4749                 }
4750                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4751                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4752         }
4753         return true;
4754 }
4755
4756 void R_AnimCache_CacheVisibleEntities(void)
4757 {
4758         int i;
4759         qboolean wantnormals = true;
4760         qboolean wanttangents = !r_showsurfaces.integer;
4761
4762         switch(vid.renderpath)
4763         {
4764         case RENDERPATH_GL20:
4765         case RENDERPATH_D3D9:
4766         case RENDERPATH_D3D10:
4767         case RENDERPATH_D3D11:
4768         case RENDERPATH_GLES2:
4769                 break;
4770         case RENDERPATH_GL11:
4771         case RENDERPATH_GL13:
4772         case RENDERPATH_GLES1:
4773                 wanttangents = false;
4774                 break;
4775         case RENDERPATH_SOFT:
4776                 break;
4777         }
4778
4779         if (r_shownormals.integer)
4780                 wanttangents = wantnormals = true;
4781
4782         // TODO: thread this
4783         // NOTE: R_PrepareRTLights() also caches entities
4784
4785         for (i = 0;i < r_refdef.scene.numentities;i++)
4786                 if (r_refdef.viewcache.entityvisible[i])
4787                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4788 }
4789
4790 //==================================================================================
4791
4792 extern cvar_t r_overheadsprites_pushback;
4793
4794 static void R_View_UpdateEntityLighting (void)
4795 {
4796         int i;
4797         entity_render_t *ent;
4798         vec3_t tempdiffusenormal, avg;
4799         vec_t f, fa, fd, fdd;
4800         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4801
4802         for (i = 0;i < r_refdef.scene.numentities;i++)
4803         {
4804                 ent = r_refdef.scene.entities[i];
4805
4806                 // skip unseen models and models that updated by CSQC
4807                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4808                         continue;
4809
4810                 // skip bsp models
4811                 if (ent->model && ent->model->brush.num_leafs)
4812                 {
4813                         // TODO: use modellight for r_ambient settings on world?
4814                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4815                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4816                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4817                         continue;
4818                 }
4819
4820                 // fetch the lighting from the worldmodel data
4821                 VectorClear(ent->modellight_ambient);
4822                 VectorClear(ent->modellight_diffuse);
4823                 VectorClear(tempdiffusenormal);
4824                 if (ent->flags & RENDER_LIGHT)
4825                 {
4826                         vec3_t org;
4827                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4828
4829                         // complete lightning for lit sprites
4830                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4831                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4832                         {
4833                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4834                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4835                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4836                         }
4837                         else
4838                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4839
4840                         if(ent->flags & RENDER_EQUALIZE)
4841                         {
4842                                 // first fix up ambient lighting...
4843                                 if(r_equalize_entities_minambient.value > 0)
4844                                 {
4845                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4846                                         if(fd > 0)
4847                                         {
4848                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4849                                                 if(fa < r_equalize_entities_minambient.value * fd)
4850                                                 {
4851                                                         // solve:
4852                                                         //   fa'/fd' = minambient
4853                                                         //   fa'+0.25*fd' = fa+0.25*fd
4854                                                         //   ...
4855                                                         //   fa' = fd' * minambient
4856                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4857                                                         //   ...
4858                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4859                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4860                                                         //   ...
4861                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4862                                                         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
4863                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4864                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4865                                                 }
4866                                         }
4867                                 }
4868
4869                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4870                                 {
4871                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4872                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4873                                         f = fa + 0.25 * fd;
4874                                         if(f > 0)
4875                                         {
4876                                                 // adjust brightness and saturation to target
4877                                                 avg[0] = avg[1] = avg[2] = fa / f;
4878                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4879                                                 avg[0] = avg[1] = avg[2] = fd / f;
4880                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4881                                         }
4882                                 }
4883                         }
4884                 }
4885                 else // highly rare
4886                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4887
4888                 // move the light direction into modelspace coordinates for lighting code
4889                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4890                 if(VectorLength2(ent->modellight_lightdir) == 0)
4891                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4892                 VectorNormalize(ent->modellight_lightdir);
4893         }
4894 }
4895
4896 #define MAX_LINEOFSIGHTTRACES 64
4897
4898 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4899 {
4900         int i;
4901         vec3_t boxmins, boxmaxs;
4902         vec3_t start;
4903         vec3_t end;
4904         dp_model_t *model = r_refdef.scene.worldmodel;
4905
4906         if (!model || !model->brush.TraceLineOfSight)
4907                 return true;
4908
4909         // expand the box a little
4910         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4911         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4912         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4913         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4914         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4915         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4916
4917         // return true if eye is inside enlarged box
4918         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4919                 return true;
4920
4921         // try center
4922         VectorCopy(eye, start);
4923         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4924         if (model->brush.TraceLineOfSight(model, start, end))
4925                 return true;
4926
4927         // try various random positions
4928         for (i = 0;i < numsamples;i++)
4929         {
4930                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4931                 if (model->brush.TraceLineOfSight(model, start, end))
4932                         return true;
4933         }
4934
4935         return false;
4936 }
4937
4938
4939 static void R_View_UpdateEntityVisible (void)
4940 {
4941         int i;
4942         int renderimask;
4943         int samples;
4944         entity_render_t *ent;
4945
4946         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4947                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4948                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4949                 :                                                          RENDER_EXTERIORMODEL;
4950         if (!r_drawviewmodel.integer)
4951                 renderimask |= RENDER_VIEWMODEL;
4952         if (!r_drawexteriormodel.integer)
4953                 renderimask |= RENDER_EXTERIORMODEL;
4954         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4955         {
4956                 // worldmodel can check visibility
4957                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4958                 for (i = 0;i < r_refdef.scene.numentities;i++)
4959                 {
4960                         ent = r_refdef.scene.entities[i];
4961                         if (!(ent->flags & renderimask))
4962                         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)))
4963                         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))
4964                                 r_refdef.viewcache.entityvisible[i] = true;
4965                 }
4966         }
4967         else
4968         {
4969                 // no worldmodel or it can't check visibility
4970                 for (i = 0;i < r_refdef.scene.numentities;i++)
4971                 {
4972                         ent = r_refdef.scene.entities[i];
4973                         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));
4974                 }
4975         }
4976         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4977                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4978         {
4979                 for (i = 0;i < r_refdef.scene.numentities;i++)
4980                 {
4981                         if (!r_refdef.viewcache.entityvisible[i])
4982                                 continue;
4983                         ent = r_refdef.scene.entities[i];
4984                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4985                         {
4986                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4987                                 if (samples < 0)
4988                                         continue; // temp entities do pvs only
4989                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4990                                         ent->last_trace_visibility = realtime;
4991                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4992                                         r_refdef.viewcache.entityvisible[i] = 0;
4993                         }
4994                 }
4995         }
4996 }
4997
4998 /// only used if skyrendermasked, and normally returns false
4999 int R_DrawBrushModelsSky (void)
5000 {
5001         int i, sky;
5002         entity_render_t *ent;
5003
5004         sky = false;
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (!ent->model || !ent->model->DrawSky)
5011                         continue;
5012                 ent->model->DrawSky(ent);
5013                 sky = true;
5014         }
5015         return sky;
5016 }
5017
5018 static void R_DrawNoModel(entity_render_t *ent);
5019 static void R_DrawModels(void)
5020 {
5021         int i;
5022         entity_render_t *ent;
5023
5024         for (i = 0;i < r_refdef.scene.numentities;i++)
5025         {
5026                 if (!r_refdef.viewcache.entityvisible[i])
5027                         continue;
5028                 ent = r_refdef.scene.entities[i];
5029                 r_refdef.stats.entities++;
5030                 /*
5031                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5032                 {
5033                         vec3_t f, l, u, o;
5034                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5035                         Con_Printf("R_DrawModels\n");
5036                         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]);
5037                         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);
5038                         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);
5039                 }
5040                 */
5041                 if (ent->model && ent->model->Draw != NULL)
5042                         ent->model->Draw(ent);
5043                 else
5044                         R_DrawNoModel(ent);
5045         }
5046 }
5047
5048 static void R_DrawModelsDepth(void)
5049 {
5050         int i;
5051         entity_render_t *ent;
5052
5053         for (i = 0;i < r_refdef.scene.numentities;i++)
5054         {
5055                 if (!r_refdef.viewcache.entityvisible[i])
5056                         continue;
5057                 ent = r_refdef.scene.entities[i];
5058                 if (ent->model && ent->model->DrawDepth != NULL)
5059                         ent->model->DrawDepth(ent);
5060         }
5061 }
5062
5063 static void R_DrawModelsDebug(void)
5064 {
5065         int i;
5066         entity_render_t *ent;
5067
5068         for (i = 0;i < r_refdef.scene.numentities;i++)
5069         {
5070                 if (!r_refdef.viewcache.entityvisible[i])
5071                         continue;
5072                 ent = r_refdef.scene.entities[i];
5073                 if (ent->model && ent->model->DrawDebug != NULL)
5074                         ent->model->DrawDebug(ent);
5075         }
5076 }
5077
5078 static void R_DrawModelsAddWaterPlanes(void)
5079 {
5080         int i;
5081         entity_render_t *ent;
5082
5083         for (i = 0;i < r_refdef.scene.numentities;i++)
5084         {
5085                 if (!r_refdef.viewcache.entityvisible[i])
5086                         continue;
5087                 ent = r_refdef.scene.entities[i];
5088                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5089                         ent->model->DrawAddWaterPlanes(ent);
5090         }
5091 }
5092
5093 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}};
5094
5095 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5096 {
5097         if (r_hdr_irisadaptation.integer)
5098         {
5099                 vec3_t p;
5100                 vec3_t ambient;
5101                 vec3_t diffuse;
5102                 vec3_t diffusenormal;
5103                 vec3_t forward;
5104                 vec_t brightness = 0.0f;
5105                 vec_t goal;
5106                 vec_t current;
5107                 vec_t d;
5108                 int c;
5109                 VectorCopy(r_refdef.view.forward, forward);
5110                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5111                 {
5112                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5113                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5114                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5115                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5116                         d = DotProduct(forward, diffusenormal);
5117                         brightness += VectorLength(ambient);
5118                         if (d > 0)
5119                                 brightness += d * VectorLength(diffuse);
5120                 }
5121                 brightness *= 1.0f / c;
5122                 brightness += 0.00001f; // make sure it's never zero
5123                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5124                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5125                 current = r_hdr_irisadaptation_value.value;
5126                 if (current < goal)
5127                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5128                 else if (current > goal)
5129                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5130                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5131                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5132         }
5133         else if (r_hdr_irisadaptation_value.value != 1.0f)
5134                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5135 }
5136
5137 static void R_View_SetFrustum(const int *scissor)
5138 {
5139         int i;
5140         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5141         vec3_t forward, left, up, origin, v;
5142
5143         if(scissor)
5144         {
5145                 // flipped x coordinates (because x points left here)
5146                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5147                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5148
5149                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5150                 switch(vid.renderpath)
5151                 {
5152                         case RENDERPATH_D3D9:
5153                         case RENDERPATH_D3D10:
5154                         case RENDERPATH_D3D11:
5155                                 // non-flipped y coordinates
5156                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5157                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5158                                 break;
5159                         case RENDERPATH_SOFT:
5160                         case RENDERPATH_GL11:
5161                         case RENDERPATH_GL13:
5162                         case RENDERPATH_GL20:
5163                         case RENDERPATH_GLES1:
5164                         case RENDERPATH_GLES2:
5165                                 // non-flipped y coordinates
5166                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5167                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5168                                 break;
5169                 }
5170         }
5171
5172         // we can't trust r_refdef.view.forward and friends in reflected scenes
5173         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5174
5175 #if 0
5176         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5177         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5178         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5179         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5180         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5181         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5182         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5183         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5184         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5185         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5186         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5187         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5188 #endif
5189
5190 #if 0
5191         zNear = r_refdef.nearclip;
5192         nudge = 1.0 - 1.0 / (1<<23);
5193         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5194         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5195         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5196         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5197         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5198         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5199         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5200         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5201 #endif
5202
5203
5204
5205 #if 0
5206         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5207         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5208         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5209         r_refdef.view.frustum[0].dist = m[15] - m[12];
5210
5211         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5212         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5213         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5214         r_refdef.view.frustum[1].dist = m[15] + m[12];
5215
5216         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5217         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5218         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5219         r_refdef.view.frustum[2].dist = m[15] - m[13];
5220
5221         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5222         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5223         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5224         r_refdef.view.frustum[3].dist = m[15] + m[13];
5225
5226         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5227         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5228         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5229         r_refdef.view.frustum[4].dist = m[15] - m[14];
5230
5231         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5232         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5233         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5234         r_refdef.view.frustum[5].dist = m[15] + m[14];
5235 #endif
5236
5237         if (r_refdef.view.useperspective)
5238         {
5239                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5240                 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]);
5241                 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]);
5242                 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]);
5243                 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]);
5244
5245                 // then the normals from the corners relative to origin
5246                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5247                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5248                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5249                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5250
5251                 // in a NORMAL view, forward cross left == up
5252                 // in a REFLECTED view, forward cross left == down
5253                 // so our cross products above need to be adjusted for a left handed coordinate system
5254                 CrossProduct(forward, left, v);
5255                 if(DotProduct(v, up) < 0)
5256                 {
5257                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5258                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5259                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5260                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5261                 }
5262
5263                 // Leaving those out was a mistake, those were in the old code, and they
5264                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5265                 // I couldn't reproduce it after adding those normalizations. --blub
5266                 VectorNormalize(r_refdef.view.frustum[0].normal);
5267                 VectorNormalize(r_refdef.view.frustum[1].normal);
5268                 VectorNormalize(r_refdef.view.frustum[2].normal);
5269                 VectorNormalize(r_refdef.view.frustum[3].normal);
5270
5271                 // make the corners absolute
5272                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5273                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5274                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5275                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5276
5277                 // one more normal
5278                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5279
5280                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5281                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5282                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5283                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5284                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5285         }
5286         else
5287         {
5288                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5289                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5290                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5291                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5292                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5293                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5294                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5295                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5296                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5297                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5298         }
5299         r_refdef.view.numfrustumplanes = 5;
5300
5301         if (r_refdef.view.useclipplane)
5302         {
5303                 r_refdef.view.numfrustumplanes = 6;
5304                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5305         }
5306
5307         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5308                 PlaneClassify(r_refdef.view.frustum + i);
5309
5310         // LordHavoc: note to all quake engine coders, Quake had a special case
5311         // for 90 degrees which assumed a square view (wrong), so I removed it,
5312         // Quake2 has it disabled as well.
5313
5314         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5315         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5316         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5317         //PlaneClassify(&frustum[0]);
5318
5319         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5320         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5321         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5322         //PlaneClassify(&frustum[1]);
5323
5324         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5325         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5326         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5327         //PlaneClassify(&frustum[2]);
5328
5329         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5330         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5331         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5332         //PlaneClassify(&frustum[3]);
5333
5334         // nearclip plane
5335         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5336         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5337         //PlaneClassify(&frustum[4]);
5338 }
5339
5340 void R_View_UpdateWithScissor(const int *myscissor)
5341 {
5342         R_Main_ResizeViewCache();
5343         R_View_SetFrustum(myscissor);
5344         R_View_WorldVisibility(r_refdef.view.useclipplane);
5345         R_View_UpdateEntityVisible();
5346         R_View_UpdateEntityLighting();
5347         R_AnimCache_CacheVisibleEntities();
5348 }
5349
5350 void R_View_Update(void)
5351 {
5352         R_Main_ResizeViewCache();
5353         R_View_SetFrustum(NULL);
5354         R_View_WorldVisibility(r_refdef.view.useclipplane);
5355         R_View_UpdateEntityVisible();
5356         R_View_UpdateEntityLighting();
5357         R_AnimCache_CacheVisibleEntities();
5358 }
5359
5360 float viewscalefpsadjusted = 1.0f;
5361
5362 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5363 {
5364         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5365         scale = bound(0.03125f, scale, 1.0f);
5366         *outwidth = (int)ceil(width * scale);
5367         *outheight = (int)ceil(height * scale);
5368 }
5369
5370 void R_Mesh_SetMainRenderTargets(void)
5371 {
5372         if (r_bloomstate.fbo_framebuffer)
5373                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5374         else
5375                 R_Mesh_ResetRenderTargets();
5376 }
5377
5378 void R_SetupView(qboolean allowwaterclippingplane)
5379 {
5380         const float *customclipplane = NULL;
5381         float plane[4];
5382         int scaledwidth, scaledheight;
5383         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5384         {
5385                 // LordHavoc: couldn't figure out how to make this approach the
5386                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5387                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5388                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5389                         dist = r_refdef.view.clipplane.dist;
5390                 plane[0] = r_refdef.view.clipplane.normal[0];
5391                 plane[1] = r_refdef.view.clipplane.normal[1];
5392                 plane[2] = r_refdef.view.clipplane.normal[2];
5393                 plane[3] = -dist;
5394                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5395         }
5396
5397         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5398         if (!r_refdef.view.useperspective)
5399                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - 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);
5400         else if (vid.stencil && r_useinfinitefarclip.integer)
5401                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5402         else
5403                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5404         R_Mesh_SetMainRenderTargets();
5405         R_SetViewport(&r_refdef.view.viewport);
5406         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5407         {
5408                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5409                 float screenplane[4];
5410                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5411                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5412                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5413                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5414                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5415         }
5416 }
5417
5418 void R_EntityMatrix(const matrix4x4_t *matrix)
5419 {
5420         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5421         {
5422                 gl_modelmatrixchanged = false;
5423                 gl_modelmatrix = *matrix;
5424                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5425                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5426                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5427                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5428                 CHECKGLERROR
5429                 switch(vid.renderpath)
5430                 {
5431                 case RENDERPATH_D3D9:
5432 #ifdef SUPPORTD3D
5433                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5434                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5435 #endif
5436                         break;
5437                 case RENDERPATH_D3D10:
5438                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5439                         break;
5440                 case RENDERPATH_D3D11:
5441                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5442                         break;
5443                 case RENDERPATH_GL11:
5444                 case RENDERPATH_GL13:
5445                 case RENDERPATH_GLES1:
5446                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5447                         break;
5448                 case RENDERPATH_SOFT:
5449                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5450                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5451                         break;
5452                 case RENDERPATH_GL20:
5453                 case RENDERPATH_GLES2:
5454                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5455                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5456                         break;
5457                 }
5458         }
5459 }
5460
5461 void R_ResetViewRendering2D(void)
5462 {
5463         r_viewport_t viewport;
5464         DrawQ_Finish();
5465
5466         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5467         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);
5468         R_Mesh_ResetRenderTargets();
5469         R_SetViewport(&viewport);
5470         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5471         GL_Color(1, 1, 1, 1);
5472         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5473         GL_BlendFunc(GL_ONE, GL_ZERO);
5474         GL_ScissorTest(false);
5475         GL_DepthMask(false);
5476         GL_DepthRange(0, 1);
5477         GL_DepthTest(false);
5478         GL_DepthFunc(GL_LEQUAL);
5479         R_EntityMatrix(&identitymatrix);
5480         R_Mesh_ResetTextureState();
5481         GL_PolygonOffset(0, 0);
5482         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5483         switch(vid.renderpath)
5484         {
5485         case RENDERPATH_GL11:
5486         case RENDERPATH_GL13:
5487         case RENDERPATH_GL20:
5488         case RENDERPATH_GLES1:
5489         case RENDERPATH_GLES2:
5490                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5491                 break;
5492         case RENDERPATH_D3D9:
5493         case RENDERPATH_D3D10:
5494         case RENDERPATH_D3D11:
5495         case RENDERPATH_SOFT:
5496                 break;
5497         }
5498         GL_CullFace(GL_NONE);
5499 }
5500
5501 void R_ResetViewRendering3D(void)
5502 {
5503         DrawQ_Finish();
5504
5505         R_SetupView(true);
5506         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5507         GL_Color(1, 1, 1, 1);
5508         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5509         GL_BlendFunc(GL_ONE, GL_ZERO);
5510         GL_ScissorTest(true);
5511         GL_DepthMask(true);
5512         GL_DepthRange(0, 1);
5513         GL_DepthTest(true);
5514         GL_DepthFunc(GL_LEQUAL);
5515         R_EntityMatrix(&identitymatrix);
5516         R_Mesh_ResetTextureState();
5517         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5518         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5519         switch(vid.renderpath)
5520         {
5521         case RENDERPATH_GL11:
5522         case RENDERPATH_GL13:
5523         case RENDERPATH_GL20:
5524         case RENDERPATH_GLES1:
5525         case RENDERPATH_GLES2:
5526                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5527                 break;
5528         case RENDERPATH_D3D9:
5529         case RENDERPATH_D3D10:
5530         case RENDERPATH_D3D11:
5531         case RENDERPATH_SOFT:
5532                 break;
5533         }
5534         GL_CullFace(r_refdef.view.cullface_back);
5535 }
5536
5537 /*
5538 ================
5539 R_RenderView_UpdateViewVectors
5540 ================
5541 */
5542 static void R_RenderView_UpdateViewVectors(void)
5543 {
5544         // break apart the view matrix into vectors for various purposes
5545         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5546         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5547         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5548         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5549         // make an inverted copy of the view matrix for tracking sprites
5550         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5551 }
5552
5553 void R_RenderScene(void);
5554 void R_RenderWaterPlanes(void);
5555
5556 static void R_Water_StartFrame(void)
5557 {
5558         int i;
5559         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5560         r_waterstate_waterplane_t *p;
5561
5562         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5563                 return;
5564
5565         switch(vid.renderpath)
5566         {
5567         case RENDERPATH_GL20:
5568         case RENDERPATH_D3D9:
5569         case RENDERPATH_D3D10:
5570         case RENDERPATH_D3D11:
5571         case RENDERPATH_SOFT:
5572         case RENDERPATH_GLES2:
5573                 break;
5574         case RENDERPATH_GL11:
5575         case RENDERPATH_GL13:
5576         case RENDERPATH_GLES1:
5577                 return;
5578         }
5579
5580         // set waterwidth and waterheight to the water resolution that will be
5581         // used (often less than the screen resolution for faster rendering)
5582         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5583
5584         // calculate desired texture sizes
5585         // can't use water if the card does not support the texture size
5586         if (!r_water.integer || r_showsurfaces.integer)
5587                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5588         else if (vid.support.arb_texture_non_power_of_two)
5589         {
5590                 texturewidth = waterwidth;
5591                 textureheight = waterheight;
5592                 camerawidth = waterwidth;
5593                 cameraheight = waterheight;
5594         }
5595         else
5596         {
5597                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5598                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5599                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5600                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5601         }
5602
5603         // allocate textures as needed
5604         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5605         {
5606                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5607                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5608                 {
5609                         if (p->texture_refraction)
5610                                 R_FreeTexture(p->texture_refraction);
5611                         p->texture_refraction = NULL;
5612                         if (p->texture_reflection)
5613                                 R_FreeTexture(p->texture_reflection);
5614                         p->texture_reflection = NULL;
5615                         if (p->texture_camera)
5616                                 R_FreeTexture(p->texture_camera);
5617                         p->texture_camera = NULL;
5618                 }
5619                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5620                 r_waterstate.texturewidth = texturewidth;
5621                 r_waterstate.textureheight = textureheight;
5622                 r_waterstate.camerawidth = camerawidth;
5623                 r_waterstate.cameraheight = cameraheight;
5624         }
5625
5626         if (r_waterstate.texturewidth)
5627         {
5628                 int scaledwidth, scaledheight;
5629
5630                 r_waterstate.enabled = true;
5631
5632                 // when doing a reduced render (HDR) we want to use a smaller area
5633                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5634                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5635                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5636
5637                 // set up variables that will be used in shader setup
5638                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5639                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5640                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5641                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5642         }
5643
5644         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5645         r_waterstate.numwaterplanes = 0;
5646 }
5647
5648 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5649 {
5650         int planeindex, bestplaneindex, vertexindex;
5651         vec3_t mins, maxs, normal, center, v, n;
5652         vec_t planescore, bestplanescore;
5653         mplane_t plane;
5654         r_waterstate_waterplane_t *p;
5655         texture_t *t = R_GetCurrentTexture(surface->texture);
5656
5657         rsurface.texture = t;
5658         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5659         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5660         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5661                 return;
5662         // average the vertex normals, find the surface bounds (after deformvertexes)
5663         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5664         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5665         VectorCopy(n, normal);
5666         VectorCopy(v, mins);
5667         VectorCopy(v, maxs);
5668         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5669         {
5670                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5671                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5672                 VectorAdd(normal, n, normal);
5673                 mins[0] = min(mins[0], v[0]);
5674                 mins[1] = min(mins[1], v[1]);
5675                 mins[2] = min(mins[2], v[2]);
5676                 maxs[0] = max(maxs[0], v[0]);
5677                 maxs[1] = max(maxs[1], v[1]);
5678                 maxs[2] = max(maxs[2], v[2]);
5679         }
5680         VectorNormalize(normal);
5681         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5682
5683         VectorCopy(normal, plane.normal);
5684         VectorNormalize(plane.normal);
5685         plane.dist = DotProduct(center, plane.normal);
5686         PlaneClassify(&plane);
5687         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5688         {
5689                 // skip backfaces (except if nocullface is set)
5690 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5691 //                      return;
5692                 VectorNegate(plane.normal, plane.normal);
5693                 plane.dist *= -1;
5694                 PlaneClassify(&plane);
5695         }
5696
5697
5698         // find a matching plane if there is one
5699         bestplaneindex = -1;
5700         bestplanescore = 1048576.0f;
5701         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5702         {
5703                 if(p->camera_entity == t->camera_entity)
5704                 {
5705                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5706                         if (bestplaneindex < 0 || bestplanescore > planescore)
5707                         {
5708                                 bestplaneindex = planeindex;
5709                                 bestplanescore = planescore;
5710                         }
5711                 }
5712         }
5713         planeindex = bestplaneindex;
5714         p = r_waterstate.waterplanes + planeindex;
5715
5716         // if this surface does not fit any known plane rendered this frame, add one
5717         if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
5718         {
5719                 // store the new plane
5720                 planeindex = r_waterstate.numwaterplanes++;
5721                 p = r_waterstate.waterplanes + planeindex;
5722                 p->plane = plane;
5723                 // clear materialflags and pvs
5724                 p->materialflags = 0;
5725                 p->pvsvalid = false;
5726                 p->camera_entity = t->camera_entity;
5727                 VectorCopy(mins, p->mins);
5728                 VectorCopy(maxs, p->maxs);
5729         }
5730         else
5731         {
5732                 // merge mins/maxs when we're adding this surface to the plane
5733                 p->mins[0] = min(p->mins[0], mins[0]);
5734                 p->mins[1] = min(p->mins[1], mins[1]);
5735                 p->mins[2] = min(p->mins[2], mins[2]);
5736                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5737                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5738                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5739         }
5740         // merge this surface's materialflags into the waterplane
5741         p->materialflags |= t->currentmaterialflags;
5742         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5743         {
5744                 // merge this surface's PVS into the waterplane
5745                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5746                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5747                 {
5748                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5749                         p->pvsvalid = true;
5750                 }
5751         }
5752 }
5753
5754 extern cvar_t r_drawparticles;
5755 extern cvar_t r_drawdecals;
5756
5757 static void R_Water_ProcessPlanes(void)
5758 {
5759         int myscissor[4];
5760         r_refdef_view_t originalview;
5761         r_refdef_view_t myview;
5762         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;
5763         r_waterstate_waterplane_t *p;
5764         vec3_t visorigin;
5765
5766         originalview = r_refdef.view;
5767
5768         // lowquality hack, temporarily shut down some cvars and restore afterwards
5769         qualityreduction = r_water_lowquality.integer;
5770         if (qualityreduction > 0)
5771         {
5772                 if (qualityreduction >= 1)
5773                 {
5774                         old_r_shadows = r_shadows.integer;
5775                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5776                         old_r_dlight = r_shadow_realtime_dlight.integer;
5777                         Cvar_SetValueQuick(&r_shadows, 0);
5778                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5779                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5780                 }
5781                 if (qualityreduction >= 2)
5782                 {
5783                         old_r_dynamic = r_dynamic.integer;
5784                         old_r_particles = r_drawparticles.integer;
5785                         old_r_decals = r_drawdecals.integer;
5786                         Cvar_SetValueQuick(&r_dynamic, 0);
5787                         Cvar_SetValueQuick(&r_drawparticles, 0);
5788                         Cvar_SetValueQuick(&r_drawdecals, 0);
5789                 }
5790         }
5791
5792         // make sure enough textures are allocated
5793         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5794         {
5795                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5796                 {
5797                         if (!p->texture_refraction)
5798                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5799                         if (!p->texture_refraction)
5800                                 goto error;
5801                 }
5802                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5803                 {
5804                         if (!p->texture_camera)
5805                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5806                         if (!p->texture_camera)
5807                                 goto error;
5808                 }
5809
5810                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5811                 {
5812                         if (!p->texture_reflection)
5813                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5814                         if (!p->texture_reflection)
5815                                 goto error;
5816                 }
5817         }
5818
5819         // render views
5820         r_refdef.view = originalview;
5821         r_refdef.view.showdebug = false;
5822         r_refdef.view.width = r_waterstate.waterwidth;
5823         r_refdef.view.height = r_waterstate.waterheight;
5824         r_refdef.view.useclipplane = true;
5825         myview = r_refdef.view;
5826         r_waterstate.renderingscene = true;
5827         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5828         {
5829                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5830                 {
5831                         r_refdef.view = myview;
5832                         if(r_water_scissormode.integer)
5833                         {
5834                                 R_SetupView(true);
5835                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5836                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5837                         }
5838
5839                         // render reflected scene and copy into texture
5840                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5841                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5842                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5843                         r_refdef.view.clipplane = p->plane;
5844                         // reverse the cullface settings for this render
5845                         r_refdef.view.cullface_front = GL_FRONT;
5846                         r_refdef.view.cullface_back = GL_BACK;
5847                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5848                         {
5849                                 r_refdef.view.usecustompvs = true;
5850                                 if (p->pvsvalid)
5851                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5852                                 else
5853                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5854                         }
5855
5856                         R_ResetViewRendering3D();
5857                         R_ClearScreen(r_refdef.fogenabled);
5858                         if(r_water_scissormode.integer & 2)
5859                                 R_View_UpdateWithScissor(myscissor);
5860                         else
5861                                 R_View_Update();
5862                         if(r_water_scissormode.integer & 1)
5863                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5864                         R_RenderScene();
5865
5866                         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);
5867                 }
5868
5869                 // render the normal view scene and copy into texture
5870                 // (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)
5871                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5872                 {
5873                         r_refdef.view = myview;
5874                         if(r_water_scissormode.integer)
5875                         {
5876                                 R_SetupView(true);
5877                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5878                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5879                         }
5880
5881                         r_waterstate.renderingrefraction = true;
5882
5883                         r_refdef.view.clipplane = p->plane;
5884                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5885                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5886
5887                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5888                         {
5889                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5890                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5891                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5892                                 R_RenderView_UpdateViewVectors();
5893                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5894                                 {
5895                                         r_refdef.view.usecustompvs = true;
5896                                         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);
5897                                 }
5898                         }
5899
5900                         PlaneClassify(&r_refdef.view.clipplane);
5901
5902                         R_ResetViewRendering3D();
5903                         R_ClearScreen(r_refdef.fogenabled);
5904                         if(r_water_scissormode.integer & 2)
5905                                 R_View_UpdateWithScissor(myscissor);
5906                         else
5907                                 R_View_Update();
5908                         if(r_water_scissormode.integer & 1)
5909                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5910                         R_RenderScene();
5911
5912                         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);
5913                         r_waterstate.renderingrefraction = false;
5914                 }
5915                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5916                 {
5917                         r_refdef.view = myview;
5918
5919                         r_refdef.view.clipplane = p->plane;
5920                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5921                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5922
5923                         r_refdef.view.width = r_waterstate.camerawidth;
5924                         r_refdef.view.height = r_waterstate.cameraheight;
5925                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5926                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5927
5928                         if(p->camera_entity)
5929                         {
5930                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5931                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5932                         }
5933
5934                         // note: all of the view is used for displaying... so
5935                         // there is no use in scissoring
5936
5937                         // reverse the cullface settings for this render
5938                         r_refdef.view.cullface_front = GL_FRONT;
5939                         r_refdef.view.cullface_back = GL_BACK;
5940                         // also reverse the view matrix
5941                         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
5942                         R_RenderView_UpdateViewVectors();
5943                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5944                         {
5945                                 r_refdef.view.usecustompvs = true;
5946                                 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);
5947                         }
5948                         
5949                         // camera needs no clipplane
5950                         r_refdef.view.useclipplane = false;
5951
5952                         PlaneClassify(&r_refdef.view.clipplane);
5953
5954                         R_ResetViewRendering3D();
5955                         R_ClearScreen(r_refdef.fogenabled);
5956                         R_View_Update();
5957                         R_RenderScene();
5958
5959                         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);
5960                         r_waterstate.renderingrefraction = false;
5961                 }
5962
5963         }
5964         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5965         r_waterstate.renderingscene = false;
5966         r_refdef.view = originalview;
5967         R_ResetViewRendering3D();
5968         R_ClearScreen(r_refdef.fogenabled);
5969         R_View_Update();
5970         goto finish;
5971 error:
5972         r_refdef.view = originalview;
5973         r_waterstate.renderingscene = false;
5974         Cvar_SetValueQuick(&r_water, 0);
5975         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5976 finish:
5977         // lowquality hack, restore cvars
5978         if (qualityreduction > 0)
5979         {
5980                 if (qualityreduction >= 1)
5981                 {
5982                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5984                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5985                 }
5986                 if (qualityreduction >= 2)
5987                 {
5988                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5989                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5990                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5991                 }
5992         }
5993 }
5994
5995 void R_Bloom_StartFrame(void)
5996 {
5997         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5998         int viewwidth, viewheight;
5999         textype_t textype;
6000
6001         if (r_viewscale_fpsscaling.integer)
6002         {
6003                 double actualframetime;
6004                 double targetframetime;
6005                 double adjust;
6006                 actualframetime = r_refdef.lastdrawscreentime;
6007                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6008                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6009                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6010                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6011                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6012                 viewscalefpsadjusted += adjust;
6013                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6014         }
6015         else
6016                 viewscalefpsadjusted = 1.0f;
6017
6018         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6019
6020         switch(vid.renderpath)
6021         {
6022         case RENDERPATH_GL20:
6023         case RENDERPATH_D3D9:
6024         case RENDERPATH_D3D10:
6025         case RENDERPATH_D3D11:
6026         case RENDERPATH_SOFT:
6027         case RENDERPATH_GLES2:
6028                 break;
6029         case RENDERPATH_GL11:
6030         case RENDERPATH_GL13:
6031         case RENDERPATH_GLES1:
6032                 return;
6033         }
6034
6035         // set bloomwidth and bloomheight to the bloom resolution that will be
6036         // used (often less than the screen resolution for faster rendering)
6037         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6038         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6039         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6040         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6041         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6042
6043         // calculate desired texture sizes
6044         if (vid.support.arb_texture_non_power_of_two)
6045         {
6046                 screentexturewidth = vid.width;
6047                 screentextureheight = vid.height;
6048                 bloomtexturewidth = r_bloomstate.bloomwidth;
6049                 bloomtextureheight = r_bloomstate.bloomheight;
6050         }
6051         else
6052         {
6053                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6054                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6055                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6056                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6057         }
6058
6059         if ((r_hdr.integer || 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))
6060         {
6061                 Cvar_SetValueQuick(&r_hdr, 0);
6062                 Cvar_SetValueQuick(&r_bloom, 0);
6063                 Cvar_SetValueQuick(&r_motionblur, 0);
6064                 Cvar_SetValueQuick(&r_damageblur, 0);
6065         }
6066
6067         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
6068                 screentexturewidth = screentextureheight = 0;
6069         if (!r_hdr.integer && !r_bloom.integer)
6070                 bloomtexturewidth = bloomtextureheight = 0;
6071
6072         textype = TEXTYPE_COLORBUFFER;
6073         switch (vid.renderpath)
6074         {
6075         case RENDERPATH_GL20:
6076         case RENDERPATH_GLES2:
6077                 if (vid.support.ext_framebuffer_object)
6078                 {
6079                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6080                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6081                 }
6082                 break;
6083         case RENDERPATH_GL11:
6084         case RENDERPATH_GL13:
6085         case RENDERPATH_GLES1:
6086         case RENDERPATH_D3D9:
6087         case RENDERPATH_D3D10:
6088         case RENDERPATH_D3D11:
6089         case RENDERPATH_SOFT:
6090                 break;
6091         }
6092
6093         // allocate textures as needed
6094         if (r_bloomstate.screentexturewidth != screentexturewidth
6095          || r_bloomstate.screentextureheight != screentextureheight
6096          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6097          || r_bloomstate.bloomtextureheight != bloomtextureheight
6098          || r_bloomstate.texturetype != textype
6099          || r_bloomstate.viewfbo != r_viewfbo.integer)
6100         {
6101                 if (r_bloomstate.texture_bloom)
6102                         R_FreeTexture(r_bloomstate.texture_bloom);
6103                 r_bloomstate.texture_bloom = NULL;
6104                 if (r_bloomstate.texture_screen)
6105                         R_FreeTexture(r_bloomstate.texture_screen);
6106                 r_bloomstate.texture_screen = NULL;
6107                 if (r_bloomstate.fbo_framebuffer)
6108                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6109                 r_bloomstate.fbo_framebuffer = 0;
6110                 if (r_bloomstate.texture_framebuffercolor)
6111                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6112                 r_bloomstate.texture_framebuffercolor = NULL;
6113                 if (r_bloomstate.texture_framebufferdepth)
6114                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6115                 r_bloomstate.texture_framebufferdepth = NULL;
6116                 r_bloomstate.screentexturewidth = screentexturewidth;
6117                 r_bloomstate.screentextureheight = screentextureheight;
6118                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6119                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6120                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6121                 {
6122                         // FIXME: choose depth bits based on a cvar
6123                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6124                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6125                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6126                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6127 #ifndef USE_GLES2
6128                         // render depth into one texture and normalmap into the other
6129                         if (qglDrawBuffer)
6130                         {
6131                                 int status;
6132                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6133                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6134                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6135                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6136                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6137                         }
6138 #endif
6139                 }
6140                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6141                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6142                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6143                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6144                 r_bloomstate.viewfbo = r_viewfbo.integer;
6145                 r_bloomstate.texturetype = textype;
6146         }
6147
6148         // when doing a reduced render (HDR) we want to use a smaller area
6149         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6150         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6151         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6152         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6153         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6154
6155         // set up a texcoord array for the full resolution screen image
6156         // (we have to keep this around to copy back during final render)
6157         r_bloomstate.screentexcoord2f[0] = 0;
6158         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6159         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6160         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6161         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6162         r_bloomstate.screentexcoord2f[5] = 0;
6163         r_bloomstate.screentexcoord2f[6] = 0;
6164         r_bloomstate.screentexcoord2f[7] = 0;
6165
6166         // set up a texcoord array for the reduced resolution bloom image
6167         // (which will be additive blended over the screen image)
6168         r_bloomstate.bloomtexcoord2f[0] = 0;
6169         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6170         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6171         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6172         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6173         r_bloomstate.bloomtexcoord2f[5] = 0;
6174         r_bloomstate.bloomtexcoord2f[6] = 0;
6175         r_bloomstate.bloomtexcoord2f[7] = 0;
6176
6177         switch(vid.renderpath)
6178         {
6179         case RENDERPATH_GL11:
6180         case RENDERPATH_GL13:
6181         case RENDERPATH_GL20:
6182         case RENDERPATH_SOFT:
6183         case RENDERPATH_GLES1:
6184         case RENDERPATH_GLES2:
6185                 break;
6186         case RENDERPATH_D3D9:
6187         case RENDERPATH_D3D10:
6188         case RENDERPATH_D3D11:
6189                 {
6190                         int i;
6191                         for (i = 0;i < 4;i++)
6192                         {
6193                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6194                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6195                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6196                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6197                         }
6198                 }
6199                 break;
6200         }
6201
6202         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6203         {
6204                 r_bloomstate.enabled = true;
6205                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6206         }
6207
6208         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6209
6210         if (r_bloomstate.fbo_framebuffer)
6211                 r_refdef.view.clear = true;
6212 }
6213
6214 void R_Bloom_CopyBloomTexture(float colorscale)
6215 {
6216         r_refdef.stats.bloom++;
6217
6218         // scale down screen texture to the bloom texture size
6219         CHECKGLERROR
6220         R_Mesh_SetMainRenderTargets();
6221         R_SetViewport(&r_bloomstate.viewport);
6222         GL_BlendFunc(GL_ONE, GL_ZERO);
6223         GL_Color(colorscale, colorscale, colorscale, 1);
6224         // 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...
6225         switch(vid.renderpath)
6226         {
6227         case RENDERPATH_GL11:
6228         case RENDERPATH_GL13:
6229         case RENDERPATH_GL20:
6230         case RENDERPATH_GLES1:
6231         case RENDERPATH_GLES2:
6232         case RENDERPATH_SOFT:
6233                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6234                 break;
6235         case RENDERPATH_D3D9:
6236         case RENDERPATH_D3D10:
6237         case RENDERPATH_D3D11:
6238                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6239                 break;
6240         }
6241         // TODO: do boxfilter scale-down in shader?
6242         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6243         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6244         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6245
6246         // we now have a bloom image in the framebuffer
6247         // copy it into the bloom image texture for later processing
6248         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6249         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6250 }
6251
6252 void R_Bloom_CopyHDRTexture(void)
6253 {
6254         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6255         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6256 }
6257
6258 void R_Bloom_MakeTexture(void)
6259 {
6260         int x, range, dir;
6261         float xoffset, yoffset, r, brighten;
6262
6263         r_refdef.stats.bloom++;
6264
6265         R_ResetViewRendering2D();
6266
6267         // we have a bloom image in the framebuffer
6268         CHECKGLERROR
6269         R_SetViewport(&r_bloomstate.viewport);
6270
6271         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6272         {
6273                 x *= 2;
6274                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6275                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6276                 GL_Color(r,r,r,1);
6277                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6278                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6279                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6280                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6281
6282                 // copy the vertically blurred bloom view to a texture
6283                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6284                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6285         }
6286
6287         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6288         brighten = r_bloom_brighten.value;
6289         if (r_bloomstate.hdr)
6290                 brighten *= r_hdr_range.value;
6291         brighten = sqrt(brighten);
6292         if(range >= 1)
6293                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6294         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6295
6296         for (dir = 0;dir < 2;dir++)
6297         {
6298                 // blend on at multiple vertical offsets to achieve a vertical blur
6299                 // TODO: do offset blends using GLSL
6300                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6301                 GL_BlendFunc(GL_ONE, GL_ZERO);
6302                 for (x = -range;x <= range;x++)
6303                 {
6304                         if (!dir){xoffset = 0;yoffset = x;}
6305                         else {xoffset = x;yoffset = 0;}
6306                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6307                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6308                         // compute a texcoord array with the specified x and y offset
6309                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6310                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6311                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6312                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6313                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6314                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6315                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6316                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6317                         // this r value looks like a 'dot' particle, fading sharply to
6318                         // black at the edges
6319                         // (probably not realistic but looks good enough)
6320                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6321                         //r = brighten/(range*2+1);
6322                         r = brighten / (range * 2 + 1);
6323                         if(range >= 1)
6324                                 r *= (1 - x*x/(float)(range*range));
6325                         GL_Color(r, r, r, 1);
6326                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6327                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6328                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6329                         GL_BlendFunc(GL_ONE, GL_ONE);
6330                 }
6331
6332                 // copy the vertically blurred bloom view to a texture
6333                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6334                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6335         }
6336 }
6337
6338 void R_HDR_RenderBloomTexture(void)
6339 {
6340         int oldwidth, oldheight;
6341         float oldcolorscale;
6342         qboolean oldwaterstate;
6343
6344         oldwaterstate = r_waterstate.enabled;
6345         oldcolorscale = r_refdef.view.colorscale;
6346         oldwidth = r_refdef.view.width;
6347         oldheight = r_refdef.view.height;
6348         r_refdef.view.width = r_bloomstate.bloomwidth;
6349         r_refdef.view.height = r_bloomstate.bloomheight;
6350
6351         if(r_hdr.integer < 2)
6352                 r_waterstate.enabled = false;
6353
6354         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6355         // TODO: add exposure compensation features
6356         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6357
6358         r_refdef.view.showdebug = false;
6359         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6360
6361         R_ResetViewRendering3D();
6362
6363         R_ClearScreen(r_refdef.fogenabled);
6364         if (r_timereport_active)
6365                 R_TimeReport("HDRclear");
6366
6367         R_View_Update();
6368         if (r_timereport_active)
6369                 R_TimeReport("visibility");
6370
6371         // only do secondary renders with HDR if r_hdr is 2 or higher
6372         r_waterstate.numwaterplanes = 0;
6373         if (r_waterstate.enabled)
6374                 R_RenderWaterPlanes();
6375
6376         r_refdef.view.showdebug = true;
6377         R_RenderScene();
6378         r_waterstate.numwaterplanes = 0;
6379
6380         R_ResetViewRendering2D();
6381
6382         R_Bloom_CopyHDRTexture();
6383         R_Bloom_MakeTexture();
6384
6385         // restore the view settings
6386         r_waterstate.enabled = oldwaterstate;
6387         r_refdef.view.width = oldwidth;
6388         r_refdef.view.height = oldheight;
6389         r_refdef.view.colorscale = oldcolorscale;
6390
6391         R_ResetViewRendering3D();
6392
6393         R_ClearScreen(r_refdef.fogenabled);
6394         if (r_timereport_active)
6395                 R_TimeReport("viewclear");
6396 }
6397
6398 static void R_BlendView(void)
6399 {
6400         unsigned int permutation;
6401         float uservecs[4][4];
6402
6403         switch (vid.renderpath)
6404         {
6405         case RENDERPATH_GL20:
6406         case RENDERPATH_D3D9:
6407         case RENDERPATH_D3D10:
6408         case RENDERPATH_D3D11:
6409         case RENDERPATH_SOFT:
6410         case RENDERPATH_GLES2:
6411                 permutation =
6412                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6413                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6414                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6415                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6416                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6417
6418                 if (r_bloomstate.texture_screen)
6419                 {
6420                         // make sure the buffer is available
6421                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6422
6423                         R_ResetViewRendering2D();
6424                         R_Mesh_SetMainRenderTargets();
6425
6426                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6427                         {
6428                                 // declare variables
6429                                 float blur_factor, blur_mouseaccel, blur_velocity;
6430                                 static float blur_average; 
6431                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6432
6433                                 // set a goal for the factoring
6434                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6435                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6436                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6437                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6438                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6439                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6440
6441                                 // from the goal, pick an averaged value between goal and last value
6442                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6443                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6444                                 
6445                                 // enforce minimum amount of blur 
6446                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6447                                 
6448                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6449
6450                                 // calculate values into a standard alpha
6451                                 cl.motionbluralpha = 1 - exp(-
6452                                                 (
6453                                                  (r_motionblur.value * blur_factor / 80)
6454                                                  +
6455                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6456                                                 )
6457                                                 /
6458                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6459                                           );
6460                                 
6461                                 // randomization for the blur value to combat persistent ghosting
6462                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6463                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6464                                 
6465                                 // apply the blur
6466                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6467                                 {
6468                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6469                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6470                                         switch(vid.renderpath)
6471                                         {
6472                                         case RENDERPATH_GL11:
6473                                         case RENDERPATH_GL13:
6474                                         case RENDERPATH_GL20:
6475                                         case RENDERPATH_GLES1:
6476                                         case RENDERPATH_GLES2:
6477                                         case RENDERPATH_SOFT:
6478                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6479                                                 break;
6480                                         case RENDERPATH_D3D9:
6481                                         case RENDERPATH_D3D10:
6482                                         case RENDERPATH_D3D11:
6483                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6484                                                 break;
6485                                         }
6486                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6487                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6488                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6489                                 }
6490                                 
6491                                 // updates old view angles for next pass 
6492                                 VectorCopy(cl.viewangles, blur_oldangles);
6493                         }
6494
6495                         // copy view into the screen texture
6496                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6497                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6498                 }
6499                 else if (!r_bloomstate.texture_bloom)
6500                 {
6501                         // we may still have to do view tint...
6502                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6503                         {
6504                                 // apply a color tint to the whole view
6505                                 R_ResetViewRendering2D();
6506                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6507                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6508                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6509                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6510                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6511                         }
6512                         break; // no screen processing, no bloom, skip it
6513                 }
6514
6515                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6516                 {
6517                         // render simple bloom effect
6518                         // copy the screen and shrink it and darken it for the bloom process
6519                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6520                         // make the bloom texture
6521                         R_Bloom_MakeTexture();
6522                 }
6523
6524 #if _MSC_VER >= 1400
6525 #define sscanf sscanf_s
6526 #endif
6527                 memset(uservecs, 0, sizeof(uservecs));
6528                 if (r_glsl_postprocess_uservec1_enable.integer)
6529                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6530                 if (r_glsl_postprocess_uservec2_enable.integer)
6531                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6532                 if (r_glsl_postprocess_uservec3_enable.integer)
6533                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6534                 if (r_glsl_postprocess_uservec4_enable.integer)
6535                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6536
6537                 R_ResetViewRendering2D();
6538                 GL_Color(1, 1, 1, 1);
6539                 GL_BlendFunc(GL_ONE, GL_ZERO);
6540
6541                 switch(vid.renderpath)
6542                 {
6543                 case RENDERPATH_GL20:
6544                 case RENDERPATH_GLES2:
6545                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6546                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6547                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6548                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6549                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6550                         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]);
6551                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6552                         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]);
6553                         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]);
6554                         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]);
6555                         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]);
6556                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6557                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6558                         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);
6559                         break;
6560                 case RENDERPATH_D3D9:
6561 #ifdef SUPPORTD3D
6562                         // 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...
6563                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6564                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6565                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6566                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6567                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6568                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6569                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6570                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6571                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6572                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6573                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6574                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6575                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6576                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6577 #endif
6578                         break;
6579                 case RENDERPATH_D3D10:
6580                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6581                         break;
6582                 case RENDERPATH_D3D11:
6583                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6584                         break;
6585                 case RENDERPATH_SOFT:
6586                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6587                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6588                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6589                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6590                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6591                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6592                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6593                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6594                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6595                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6596                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6597                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6598                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6599                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6600                         break;
6601                 default:
6602                         break;
6603                 }
6604                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6605                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6606                 break;
6607         case RENDERPATH_GL11:
6608         case RENDERPATH_GL13:
6609         case RENDERPATH_GLES1:
6610                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6611                 {
6612                         // apply a color tint to the whole view
6613                         R_ResetViewRendering2D();
6614                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6615                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6616                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6617                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6618                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6619                 }
6620                 break;
6621         }
6622 }
6623
6624 matrix4x4_t r_waterscrollmatrix;
6625
6626 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6627 {
6628         // Nehahra fog
6629         if (gamemode == GAME_NEHAHRA)
6630         {
6631                 if (gl_fogenable.integer)
6632                 {
6633                         r_refdef.oldgl_fogenable = true;
6634                         r_refdef.fog_density = gl_fogdensity.value;
6635                         r_refdef.fog_red = gl_fogred.value;
6636                         r_refdef.fog_green = gl_foggreen.value;
6637                         r_refdef.fog_blue = gl_fogblue.value;
6638                         r_refdef.fog_alpha = 1;
6639                         r_refdef.fog_start = 0;
6640                         r_refdef.fog_end = gl_skyclip.value;
6641                         r_refdef.fog_height = 1<<30;
6642                         r_refdef.fog_fadedepth = 128;
6643                 }
6644                 else if (r_refdef.oldgl_fogenable)
6645                 {
6646                         r_refdef.oldgl_fogenable = false;
6647                         r_refdef.fog_density = 0;
6648                         r_refdef.fog_red = 0;
6649                         r_refdef.fog_green = 0;
6650                         r_refdef.fog_blue = 0;
6651                         r_refdef.fog_alpha = 0;
6652                         r_refdef.fog_start = 0;
6653                         r_refdef.fog_end = 0;
6654                         r_refdef.fog_height = 1<<30;
6655                         r_refdef.fog_fadedepth = 128;
6656                 }
6657         }
6658
6659         // fog parms
6660         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6661         r_refdef.fog_start = max(0, r_refdef.fog_start);
6662         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6663
6664         if (r_refdef.fog_density && r_drawfog.integer)
6665         {
6666                 r_refdef.fogenabled = true;
6667                 // this is the point where the fog reaches 0.9986 alpha, which we
6668                 // consider a good enough cutoff point for the texture
6669                 // (0.9986 * 256 == 255.6)
6670                 if (r_fog_exp2.integer)
6671                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6672                 else
6673                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6674                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6675                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6676                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6677                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6678                         R_BuildFogHeightTexture();
6679                 // fog color was already set
6680                 // update the fog texture
6681                 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)
6682                         R_BuildFogTexture();
6683                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6684                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6685         }
6686         else
6687                 r_refdef.fogenabled = false;
6688
6689         // fog color
6690         if (r_refdef.fog_density)
6691         {
6692                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6693                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6694                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6695
6696                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6697                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6698                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6699                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6700
6701                 {
6702                         vec3_t fogvec;
6703                         VectorCopy(r_refdef.fogcolor, fogvec);
6704                         //   color.rgb *= ContrastBoost * SceneBrightness;
6705                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6706                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6707                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6708                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6709                 }
6710         }
6711 }
6712
6713 void R_UpdateVariables(void)
6714 {
6715         R_Textures_Frame();
6716
6717         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6718
6719         r_refdef.farclip = r_farclip_base.value;
6720         if (r_refdef.scene.worldmodel)
6721                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6722         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6723
6724         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6725                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6726         r_refdef.polygonfactor = 0;
6727         r_refdef.polygonoffset = 0;
6728         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6729         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6730
6731         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6732         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6733         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6734         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6735         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6736         if (FAKELIGHT_ENABLED)
6737         {
6738                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6739         }
6740         if (r_showsurfaces.integer)
6741         {
6742                 r_refdef.scene.rtworld = false;
6743                 r_refdef.scene.rtworldshadows = false;
6744                 r_refdef.scene.rtdlight = false;
6745                 r_refdef.scene.rtdlightshadows = false;
6746                 r_refdef.lightmapintensity = 0;
6747         }
6748
6749         switch(vid.renderpath)
6750         {
6751         case RENDERPATH_GL20:
6752         case RENDERPATH_D3D9:
6753         case RENDERPATH_D3D10:
6754         case RENDERPATH_D3D11:
6755         case RENDERPATH_SOFT:
6756         case RENDERPATH_GLES2:
6757                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6758                 {
6759                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6760                         {
6761                                 // build GLSL gamma texture
6762 #define RAMPWIDTH 256
6763                                 unsigned short ramp[RAMPWIDTH * 3];
6764                                 unsigned char rampbgr[RAMPWIDTH][4];
6765                                 int i;
6766
6767                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6768
6769                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6770                                 for(i = 0; i < RAMPWIDTH; ++i)
6771                                 {
6772                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6773                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6774                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6775                                         rampbgr[i][3] = 0;
6776                                 }
6777                                 if (r_texture_gammaramps)
6778                                 {
6779                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6780                                 }
6781                                 else
6782                                 {
6783                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6784                                 }
6785                         }
6786                 }
6787                 else
6788                 {
6789                         // remove GLSL gamma texture
6790                 }
6791                 break;
6792         case RENDERPATH_GL11:
6793         case RENDERPATH_GL13:
6794         case RENDERPATH_GLES1:
6795                 break;
6796         }
6797 }
6798
6799 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6800 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6801 /*
6802 ================
6803 R_SelectScene
6804 ================
6805 */
6806 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6807         if( scenetype != r_currentscenetype ) {
6808                 // store the old scenetype
6809                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6810                 r_currentscenetype = scenetype;
6811                 // move in the new scene
6812                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6813         }
6814 }
6815
6816 /*
6817 ================
6818 R_GetScenePointer
6819 ================
6820 */
6821 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6822 {
6823         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6824         if( scenetype == r_currentscenetype ) {
6825                 return &r_refdef.scene;
6826         } else {
6827                 return &r_scenes_store[ scenetype ];
6828         }
6829 }
6830
6831 int R_SortEntities_Compare(const void *ap, const void *bp)
6832 {
6833         const entity_render_t *a = *(const entity_render_t **)ap;
6834         const entity_render_t *b = *(const entity_render_t **)bp;
6835
6836         // 1. compare model
6837         if(a->model < b->model)
6838                 return -1;
6839         if(a->model > b->model)
6840                 return +1;
6841
6842         // 2. compare skin
6843         // TODO possibly calculate the REAL skinnum here first using
6844         // skinscenes?
6845         if(a->skinnum < b->skinnum)
6846                 return -1;
6847         if(a->skinnum > b->skinnum)
6848                 return +1;
6849
6850         // everything we compared is equal
6851         return 0;
6852 }
6853 void R_SortEntities(void)
6854 {
6855         // below or equal 2 ents, sorting never gains anything
6856         if(r_refdef.scene.numentities <= 2)
6857                 return;
6858         // sort
6859         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6860 }
6861
6862 /*
6863 ================
6864 R_RenderView
6865 ================
6866 */
6867 int dpsoftrast_test;
6868 extern void R_Shadow_UpdateBounceGridTexture(void);
6869 extern cvar_t r_shadow_bouncegrid;
6870 void R_RenderView(void)
6871 {
6872         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6873
6874         dpsoftrast_test = r_test.integer;
6875
6876         if (r_timereport_active)
6877                 R_TimeReport("start");
6878         r_textureframe++; // used only by R_GetCurrentTexture
6879         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6880
6881         if(R_CompileShader_CheckStaticParms())
6882                 R_GLSL_Restart_f();
6883
6884         if (!r_drawentities.integer)
6885                 r_refdef.scene.numentities = 0;
6886         else if (r_sortentities.integer)
6887                 R_SortEntities();
6888
6889         R_AnimCache_ClearCache();
6890         R_FrameData_NewFrame();
6891
6892         /* adjust for stereo display */
6893         if(R_Stereo_Active())
6894         {
6895                 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);
6896                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6897         }
6898
6899         if (r_refdef.view.isoverlay)
6900         {
6901                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6902                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6903                 R_TimeReport("depthclear");
6904
6905                 r_refdef.view.showdebug = false;
6906
6907                 r_waterstate.enabled = false;
6908                 r_waterstate.numwaterplanes = 0;
6909
6910                 R_RenderScene();
6911
6912                 r_refdef.view.matrix = originalmatrix;
6913
6914                 CHECKGLERROR
6915                 return;
6916         }
6917
6918         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6919         {
6920                 r_refdef.view.matrix = originalmatrix;
6921                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6922         }
6923
6924         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6925
6926         R_RenderView_UpdateViewVectors();
6927
6928         R_Shadow_UpdateWorldLightSelection();
6929
6930         R_Bloom_StartFrame();
6931         R_Water_StartFrame();
6932
6933         CHECKGLERROR
6934         if (r_timereport_active)
6935                 R_TimeReport("viewsetup");
6936
6937         R_ResetViewRendering3D();
6938
6939         if (r_refdef.view.clear || r_refdef.fogenabled)
6940         {
6941                 R_ClearScreen(r_refdef.fogenabled);
6942                 if (r_timereport_active)
6943                         R_TimeReport("viewclear");
6944         }
6945         r_refdef.view.clear = true;
6946
6947         // this produces a bloom texture to be used in R_BlendView() later
6948         if (r_bloomstate.hdr)
6949         {
6950                 R_HDR_RenderBloomTexture();
6951                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6952                 r_textureframe++; // used only by R_GetCurrentTexture
6953         }
6954
6955         r_refdef.view.showdebug = true;
6956
6957         R_View_Update();
6958         if (r_timereport_active)
6959                 R_TimeReport("visibility");
6960
6961         R_Shadow_UpdateBounceGridTexture();
6962         if (r_timereport_active && r_shadow_bouncegrid.integer)
6963                 R_TimeReport("bouncegrid");
6964
6965         r_waterstate.numwaterplanes = 0;
6966         if (r_waterstate.enabled)
6967                 R_RenderWaterPlanes();
6968
6969         R_RenderScene();
6970         r_waterstate.numwaterplanes = 0;
6971
6972         R_BlendView();
6973         if (r_timereport_active)
6974                 R_TimeReport("blendview");
6975
6976         GL_Scissor(0, 0, vid.width, vid.height);
6977         GL_ScissorTest(false);
6978
6979         r_refdef.view.matrix = originalmatrix;
6980
6981         CHECKGLERROR
6982 }
6983
6984 void R_RenderWaterPlanes(void)
6985 {
6986         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6987         {
6988                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6989                 if (r_timereport_active)
6990                         R_TimeReport("waterworld");
6991         }
6992
6993         // don't let sound skip if going slow
6994         if (r_refdef.scene.extraupdate)
6995                 S_ExtraUpdate ();
6996
6997         R_DrawModelsAddWaterPlanes();
6998         if (r_timereport_active)
6999                 R_TimeReport("watermodels");
7000
7001         if (r_waterstate.numwaterplanes)
7002         {
7003                 R_Water_ProcessPlanes();
7004                 if (r_timereport_active)
7005                         R_TimeReport("waterscenes");
7006         }
7007 }
7008
7009 extern void R_DrawLightningBeams (void);
7010 extern void VM_CL_AddPolygonsToMeshQueue (void);
7011 extern void R_DrawPortals (void);
7012 extern cvar_t cl_locs_show;
7013 static void R_DrawLocs(void);
7014 static void R_DrawEntityBBoxes(void);
7015 static void R_DrawModelDecals(void);
7016 extern void R_DrawModelShadows(void);
7017 extern void R_DrawModelShadowMaps(void);
7018 extern cvar_t cl_decals_newsystem;
7019 extern qboolean r_shadow_usingdeferredprepass;
7020 void R_RenderScene(void)
7021 {
7022         qboolean shadowmapping = false;
7023
7024         if (r_timereport_active)
7025                 R_TimeReport("beginscene");
7026
7027         r_refdef.stats.renders++;
7028
7029         R_UpdateFog();
7030
7031         // don't let sound skip if going slow
7032         if (r_refdef.scene.extraupdate)
7033                 S_ExtraUpdate ();
7034
7035         R_MeshQueue_BeginScene();
7036
7037         R_SkyStartFrame();
7038
7039         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);
7040
7041         if (r_timereport_active)
7042                 R_TimeReport("skystartframe");
7043
7044         if (cl.csqc_vidvars.drawworld)
7045         {
7046                 // don't let sound skip if going slow
7047                 if (r_refdef.scene.extraupdate)
7048                         S_ExtraUpdate ();
7049
7050                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7051                 {
7052                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7053                         if (r_timereport_active)
7054                                 R_TimeReport("worldsky");
7055                 }
7056
7057                 if (R_DrawBrushModelsSky() && r_timereport_active)
7058                         R_TimeReport("bmodelsky");
7059
7060                 if (skyrendermasked && skyrenderlater)
7061                 {
7062                         // we have to force off the water clipping plane while rendering sky
7063                         R_SetupView(false);
7064                         R_Sky();
7065                         R_SetupView(true);
7066                         if (r_timereport_active)
7067                                 R_TimeReport("sky");
7068                 }
7069         }
7070
7071         R_Shadow_PrepareLights();
7072         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7073                 R_Shadow_PrepareModelShadows();
7074         if (r_timereport_active)
7075                 R_TimeReport("preparelights");
7076
7077         if (R_Shadow_ShadowMappingEnabled())
7078                 shadowmapping = true;
7079
7080         if (r_shadow_usingdeferredprepass)
7081                 R_Shadow_DrawPrepass();
7082
7083         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7084         {
7085                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7086                 if (r_timereport_active)
7087                         R_TimeReport("worlddepth");
7088         }
7089         if (r_depthfirst.integer >= 2)
7090         {
7091                 R_DrawModelsDepth();
7092                 if (r_timereport_active)
7093                         R_TimeReport("modeldepth");
7094         }
7095
7096         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7097         {
7098                 R_DrawModelShadowMaps();
7099                 R_ResetViewRendering3D();
7100                 // don't let sound skip if going slow
7101                 if (r_refdef.scene.extraupdate)
7102                         S_ExtraUpdate ();
7103         }
7104
7105         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7106         {
7107                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7108                 if (r_timereport_active)
7109                         R_TimeReport("world");
7110         }
7111
7112         // don't let sound skip if going slow
7113         if (r_refdef.scene.extraupdate)
7114                 S_ExtraUpdate ();
7115
7116         R_DrawModels();
7117         if (r_timereport_active)
7118                 R_TimeReport("models");
7119
7120         // don't let sound skip if going slow
7121         if (r_refdef.scene.extraupdate)
7122                 S_ExtraUpdate ();
7123
7124         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7125         {
7126                 R_DrawModelShadows();
7127                 R_ResetViewRendering3D();
7128                 // don't let sound skip if going slow
7129                 if (r_refdef.scene.extraupdate)
7130                         S_ExtraUpdate ();
7131         }
7132
7133         if (!r_shadow_usingdeferredprepass)
7134         {
7135                 R_Shadow_DrawLights();
7136                 if (r_timereport_active)
7137                         R_TimeReport("rtlights");
7138         }
7139
7140         // don't let sound skip if going slow
7141         if (r_refdef.scene.extraupdate)
7142                 S_ExtraUpdate ();
7143
7144         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7145         {
7146                 R_DrawModelShadows();
7147                 R_ResetViewRendering3D();
7148                 // don't let sound skip if going slow
7149                 if (r_refdef.scene.extraupdate)
7150                         S_ExtraUpdate ();
7151         }
7152
7153         if (cl.csqc_vidvars.drawworld)
7154         {
7155                 if (cl_decals_newsystem.integer)
7156                 {
7157                         R_DrawModelDecals();
7158                         if (r_timereport_active)
7159                                 R_TimeReport("modeldecals");
7160                 }
7161                 else
7162                 {
7163                         R_DrawDecals();
7164                         if (r_timereport_active)
7165                                 R_TimeReport("decals");
7166                 }
7167
7168                 R_DrawParticles();
7169                 if (r_timereport_active)
7170                         R_TimeReport("particles");
7171
7172                 R_DrawExplosions();
7173                 if (r_timereport_active)
7174                         R_TimeReport("explosions");
7175
7176                 R_DrawLightningBeams();
7177                 if (r_timereport_active)
7178                         R_TimeReport("lightning");
7179         }
7180
7181         VM_CL_AddPolygonsToMeshQueue();
7182
7183         if (r_refdef.view.showdebug)
7184         {
7185                 if (cl_locs_show.integer)
7186                 {
7187                         R_DrawLocs();
7188                         if (r_timereport_active)
7189                                 R_TimeReport("showlocs");
7190                 }
7191
7192                 if (r_drawportals.integer)
7193                 {
7194                         R_DrawPortals();
7195                         if (r_timereport_active)
7196                                 R_TimeReport("portals");
7197                 }
7198
7199                 if (r_showbboxes.value > 0)
7200                 {
7201                         R_DrawEntityBBoxes();
7202                         if (r_timereport_active)
7203                                 R_TimeReport("bboxes");
7204                 }
7205         }
7206
7207         if (r_transparent.integer)
7208         {
7209                 R_MeshQueue_RenderTransparent();
7210                 if (r_timereport_active)
7211                         R_TimeReport("drawtrans");
7212         }
7213
7214         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))
7215         {
7216                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7217                 if (r_timereport_active)
7218                         R_TimeReport("worlddebug");
7219                 R_DrawModelsDebug();
7220                 if (r_timereport_active)
7221                         R_TimeReport("modeldebug");
7222         }
7223
7224         if (cl.csqc_vidvars.drawworld)
7225         {
7226                 R_Shadow_DrawCoronas();
7227                 if (r_timereport_active)
7228                         R_TimeReport("coronas");
7229         }
7230
7231 #if 0
7232         {
7233                 GL_DepthTest(false);
7234                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7235                 GL_Color(1, 1, 1, 1);
7236                 qglBegin(GL_POLYGON);
7237                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7238                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7239                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7240                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7241                 qglEnd();
7242                 qglBegin(GL_POLYGON);
7243                 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]);
7244                 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]);
7245                 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]);
7246                 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]);
7247                 qglEnd();
7248                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7249         }
7250 #endif
7251
7252         // don't let sound skip if going slow
7253         if (r_refdef.scene.extraupdate)
7254                 S_ExtraUpdate ();
7255
7256         R_ResetViewRendering2D();
7257 }
7258
7259 static const unsigned short bboxelements[36] =
7260 {
7261         5, 1, 3, 5, 3, 7,
7262         6, 2, 0, 6, 0, 4,
7263         7, 3, 2, 7, 2, 6,
7264         4, 0, 1, 4, 1, 5,
7265         4, 5, 7, 4, 7, 6,
7266         1, 0, 2, 1, 2, 3,
7267 };
7268
7269 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7270 {
7271         int i;
7272         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7273
7274         RSurf_ActiveWorldEntity();
7275
7276         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7277         GL_DepthMask(false);
7278         GL_DepthRange(0, 1);
7279         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7280 //      R_Mesh_ResetTextureState();
7281
7282         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7283         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7284         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7285         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7286         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7287         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7288         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7289         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7290         R_FillColors(color4f, 8, cr, cg, cb, ca);
7291         if (r_refdef.fogenabled)
7292         {
7293                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7294                 {
7295                         f1 = RSurf_FogVertex(v);
7296                         f2 = 1 - f1;
7297                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7298                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7299                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7300                 }
7301         }
7302         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7303         R_Mesh_ResetTextureState();
7304         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7305         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7306 }
7307
7308 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7309 {
7310         int i;
7311         float color[4];
7312         prvm_edict_t *edict;
7313         prvm_prog_t *prog_save = prog;
7314
7315         // this function draws bounding boxes of server entities
7316         if (!sv.active)
7317                 return;
7318
7319         GL_CullFace(GL_NONE);
7320         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7321
7322         prog = 0;
7323         SV_VM_Begin();
7324         for (i = 0;i < numsurfaces;i++)
7325         {
7326                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7327                 switch ((int)PRVM_serveredictfloat(edict, solid))
7328                 {
7329                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7330                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7331                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7332                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7333                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7334                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7335                 }
7336                 color[3] *= r_showbboxes.value;
7337                 color[3] = bound(0, color[3], 1);
7338                 GL_DepthTest(!r_showdisabledepthtest.integer);
7339                 GL_CullFace(r_refdef.view.cullface_front);
7340                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7341         }
7342         SV_VM_End();
7343         prog = prog_save;
7344 }
7345
7346 static void R_DrawEntityBBoxes(void)
7347 {
7348         int i;
7349         prvm_edict_t *edict;
7350         vec3_t center;
7351         prvm_prog_t *prog_save = prog;
7352
7353         // this function draws bounding boxes of server entities
7354         if (!sv.active)
7355                 return;
7356
7357         prog = 0;
7358         SV_VM_Begin();
7359         for (i = 0;i < prog->num_edicts;i++)
7360         {
7361                 edict = PRVM_EDICT_NUM(i);
7362                 if (edict->priv.server->free)
7363                         continue;
7364                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7365                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7366                         continue;
7367                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7368                         continue;
7369                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7370                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7371         }
7372         SV_VM_End();
7373         prog = prog_save;
7374 }
7375
7376 static const int nomodelelement3i[24] =
7377 {
7378         5, 2, 0,
7379         5, 1, 2,
7380         5, 0, 3,
7381         5, 3, 1,
7382         0, 2, 4,
7383         2, 1, 4,
7384         3, 0, 4,
7385         1, 3, 4
7386 };
7387
7388 static const unsigned short nomodelelement3s[24] =
7389 {
7390         5, 2, 0,
7391         5, 1, 2,
7392         5, 0, 3,
7393         5, 3, 1,
7394         0, 2, 4,
7395         2, 1, 4,
7396         3, 0, 4,
7397         1, 3, 4
7398 };
7399
7400 static const float nomodelvertex3f[6*3] =
7401 {
7402         -16,   0,   0,
7403          16,   0,   0,
7404           0, -16,   0,
7405           0,  16,   0,
7406           0,   0, -16,
7407           0,   0,  16
7408 };
7409
7410 static const float nomodelcolor4f[6*4] =
7411 {
7412         0.0f, 0.0f, 0.5f, 1.0f,
7413         0.0f, 0.0f, 0.5f, 1.0f,
7414         0.0f, 0.5f, 0.0f, 1.0f,
7415         0.0f, 0.5f, 0.0f, 1.0f,
7416         0.5f, 0.0f, 0.0f, 1.0f,
7417         0.5f, 0.0f, 0.0f, 1.0f
7418 };
7419
7420 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7421 {
7422         int i;
7423         float f1, f2, *c;
7424         float color4f[6*4];
7425
7426         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);
7427
7428         // this is only called once per entity so numsurfaces is always 1, and
7429         // surfacelist is always {0}, so this code does not handle batches
7430
7431         if (rsurface.ent_flags & RENDER_ADDITIVE)
7432         {
7433                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7434                 GL_DepthMask(false);
7435         }
7436         else if (rsurface.colormod[3] < 1)
7437         {
7438                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7439                 GL_DepthMask(false);
7440         }
7441         else
7442         {
7443                 GL_BlendFunc(GL_ONE, GL_ZERO);
7444                 GL_DepthMask(true);
7445         }
7446         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7447         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7448         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7449         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7450         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7451         for (i = 0, c = color4f;i < 6;i++, c += 4)
7452         {
7453                 c[0] *= rsurface.colormod[0];
7454                 c[1] *= rsurface.colormod[1];
7455                 c[2] *= rsurface.colormod[2];
7456                 c[3] *= rsurface.colormod[3];
7457         }
7458         if (r_refdef.fogenabled)
7459         {
7460                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7461                 {
7462                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7463                         f2 = 1 - f1;
7464                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7465                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7466                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7467                 }
7468         }
7469 //      R_Mesh_ResetTextureState();
7470         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7471         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7472         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7473 }
7474
7475 void R_DrawNoModel(entity_render_t *ent)
7476 {
7477         vec3_t org;
7478         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7479         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7480                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7481         else
7482                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7483 }
7484
7485 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7486 {
7487         vec3_t right1, right2, diff, normal;
7488
7489         VectorSubtract (org2, org1, normal);
7490
7491         // calculate 'right' vector for start
7492         VectorSubtract (r_refdef.view.origin, org1, diff);
7493         CrossProduct (normal, diff, right1);
7494         VectorNormalize (right1);
7495
7496         // calculate 'right' vector for end
7497         VectorSubtract (r_refdef.view.origin, org2, diff);
7498         CrossProduct (normal, diff, right2);
7499         VectorNormalize (right2);
7500
7501         vert[ 0] = org1[0] + width * right1[0];
7502         vert[ 1] = org1[1] + width * right1[1];
7503         vert[ 2] = org1[2] + width * right1[2];
7504         vert[ 3] = org1[0] - width * right1[0];
7505         vert[ 4] = org1[1] - width * right1[1];
7506         vert[ 5] = org1[2] - width * right1[2];
7507         vert[ 6] = org2[0] - width * right2[0];
7508         vert[ 7] = org2[1] - width * right2[1];
7509         vert[ 8] = org2[2] - width * right2[2];
7510         vert[ 9] = org2[0] + width * right2[0];
7511         vert[10] = org2[1] + width * right2[1];
7512         vert[11] = org2[2] + width * right2[2];
7513 }
7514
7515 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)
7516 {
7517         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7518         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7519         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7520         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7521         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7522         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7523         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7524         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7525         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7526         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7527         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7528         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7529 }
7530
7531 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7532 {
7533         int i;
7534         float *vertex3f;
7535         float v[3];
7536         VectorSet(v, x, y, z);
7537         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7538                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7539                         break;
7540         if (i == mesh->numvertices)
7541         {
7542                 if (mesh->numvertices < mesh->maxvertices)
7543                 {
7544                         VectorCopy(v, vertex3f);
7545                         mesh->numvertices++;
7546                 }
7547                 return mesh->numvertices;
7548         }
7549         else
7550                 return i;
7551 }
7552
7553 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7554 {
7555         int i;
7556         int *e, element[3];
7557         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7558         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7559         e = mesh->element3i + mesh->numtriangles * 3;
7560         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7561         {
7562                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7563                 if (mesh->numtriangles < mesh->maxtriangles)
7564                 {
7565                         *e++ = element[0];
7566                         *e++ = element[1];
7567                         *e++ = element[2];
7568                         mesh->numtriangles++;
7569                 }
7570                 element[1] = element[2];
7571         }
7572 }
7573
7574 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7575 {
7576         int i;
7577         int *e, element[3];
7578         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7579         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7580         e = mesh->element3i + mesh->numtriangles * 3;
7581         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7582         {
7583                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7584                 if (mesh->numtriangles < mesh->maxtriangles)
7585                 {
7586                         *e++ = element[0];
7587                         *e++ = element[1];
7588                         *e++ = element[2];
7589                         mesh->numtriangles++;
7590                 }
7591                 element[1] = element[2];
7592         }
7593 }
7594
7595 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7596 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7597 {
7598         int planenum, planenum2;
7599         int w;
7600         int tempnumpoints;
7601         mplane_t *plane, *plane2;
7602         double maxdist;
7603         double temppoints[2][256*3];
7604         // figure out how large a bounding box we need to properly compute this brush
7605         maxdist = 0;
7606         for (w = 0;w < numplanes;w++)
7607                 maxdist = max(maxdist, fabs(planes[w].dist));
7608         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7609         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7610         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7611         {
7612                 w = 0;
7613                 tempnumpoints = 4;
7614                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7615                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7616                 {
7617                         if (planenum2 == planenum)
7618                                 continue;
7619                         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);
7620                         w = !w;
7621                 }
7622                 if (tempnumpoints < 3)
7623                         continue;
7624                 // generate elements forming a triangle fan for this polygon
7625                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7626         }
7627 }
7628
7629 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)
7630 {
7631         texturelayer_t *layer;
7632         layer = t->currentlayers + t->currentnumlayers++;
7633         layer->type = type;
7634         layer->depthmask = depthmask;
7635         layer->blendfunc1 = blendfunc1;
7636         layer->blendfunc2 = blendfunc2;
7637         layer->texture = texture;
7638         layer->texmatrix = *matrix;
7639         layer->color[0] = r;
7640         layer->color[1] = g;
7641         layer->color[2] = b;
7642         layer->color[3] = a;
7643 }
7644
7645 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7646 {
7647         if(parms[0] == 0 && parms[1] == 0)
7648                 return false;
7649         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7650                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7651                         return false;
7652         return true;
7653 }
7654
7655 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7656 {
7657         double index, f;
7658         index = parms[2] + rsurface.shadertime * parms[3];
7659         index -= floor(index);
7660         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7661         {
7662         default:
7663         case Q3WAVEFUNC_NONE:
7664         case Q3WAVEFUNC_NOISE:
7665         case Q3WAVEFUNC_COUNT:
7666                 f = 0;
7667                 break;
7668         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7669         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7670         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7671         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7672         case Q3WAVEFUNC_TRIANGLE:
7673                 index *= 4;
7674                 f = index - floor(index);
7675                 if (index < 1)
7676                 {
7677                         // f = f;
7678                 }
7679                 else if (index < 2)
7680                         f = 1 - f;
7681                 else if (index < 3)
7682                         f = -f;
7683                 else
7684                         f = -(1 - f);
7685                 break;
7686         }
7687         f = parms[0] + parms[1] * f;
7688         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7689                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7690         return (float) f;
7691 }
7692
7693 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7694 {
7695         int w, h, idx;
7696         double f;
7697         double offsetd[2];
7698         float tcmat[12];
7699         matrix4x4_t matrix, temp;
7700         switch(tcmod->tcmod)
7701         {
7702                 case Q3TCMOD_COUNT:
7703                 case Q3TCMOD_NONE:
7704                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7705                                 matrix = r_waterscrollmatrix;
7706                         else
7707                                 matrix = identitymatrix;
7708                         break;
7709                 case Q3TCMOD_ENTITYTRANSLATE:
7710                         // this is used in Q3 to allow the gamecode to control texcoord
7711                         // scrolling on the entity, which is not supported in darkplaces yet.
7712                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7713                         break;
7714                 case Q3TCMOD_ROTATE:
7715                         f = tcmod->parms[0] * rsurface.shadertime;
7716                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7717                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7718                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7719                         break;
7720                 case Q3TCMOD_SCALE:
7721                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7722                         break;
7723                 case Q3TCMOD_SCROLL:
7724                         // extra care is needed because of precision breakdown with large values of time
7725                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7726                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7727                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7728                         break;
7729                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7730                         w = (int) tcmod->parms[0];
7731                         h = (int) tcmod->parms[1];
7732                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7733                         f = f - floor(f);
7734                         idx = (int) floor(f * w * h);
7735                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7736                         break;
7737                 case Q3TCMOD_STRETCH:
7738                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7739                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7740                         break;
7741                 case Q3TCMOD_TRANSFORM:
7742                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7743                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7744                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7745                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7746                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7747                         break;
7748                 case Q3TCMOD_TURBULENT:
7749                         // this is handled in the RSurf_PrepareVertices function
7750                         matrix = identitymatrix;
7751                         break;
7752         }
7753         temp = *texmatrix;
7754         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7755 }
7756
7757 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7758 {
7759         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7760         char name[MAX_QPATH];
7761         skinframe_t *skinframe;
7762         unsigned char pixels[296*194];
7763         strlcpy(cache->name, skinname, sizeof(cache->name));
7764         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7765         if (developer_loading.integer)
7766                 Con_Printf("loading %s\n", name);
7767         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7768         if (!skinframe || !skinframe->base)
7769         {
7770                 unsigned char *f;
7771                 fs_offset_t filesize;
7772                 skinframe = NULL;
7773                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7774                 if (f)
7775                 {
7776                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7777                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7778                         Mem_Free(f);
7779                 }
7780         }
7781         cache->skinframe = skinframe;
7782 }
7783
7784 texture_t *R_GetCurrentTexture(texture_t *t)
7785 {
7786         int i;
7787         const entity_render_t *ent = rsurface.entity;
7788         dp_model_t *model = ent->model;
7789         q3shaderinfo_layer_tcmod_t *tcmod;
7790
7791         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7792                 return t->currentframe;
7793         t->update_lastrenderframe = r_textureframe;
7794         t->update_lastrenderentity = (void *)ent;
7795
7796         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7797                 t->camera_entity = ent->entitynumber;
7798         else
7799                 t->camera_entity = 0;
7800
7801         // switch to an alternate material if this is a q1bsp animated material
7802         {
7803                 texture_t *texture = t;
7804                 int s = rsurface.ent_skinnum;
7805                 if ((unsigned int)s >= (unsigned int)model->numskins)
7806                         s = 0;
7807                 if (model->skinscenes)
7808                 {
7809                         if (model->skinscenes[s].framecount > 1)
7810                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7811                         else
7812                                 s = model->skinscenes[s].firstframe;
7813                 }
7814                 if (s > 0)
7815                         t = t + s * model->num_surfaces;
7816                 if (t->animated)
7817                 {
7818                         // use an alternate animation if the entity's frame is not 0,
7819                         // and only if the texture has an alternate animation
7820                         if (rsurface.ent_alttextures && t->anim_total[1])
7821                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7822                         else
7823                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7824                 }
7825                 texture->currentframe = t;
7826         }
7827
7828         // update currentskinframe to be a qw skin or animation frame
7829         if (rsurface.ent_qwskin >= 0)
7830         {
7831                 i = rsurface.ent_qwskin;
7832                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7833                 {
7834                         r_qwskincache_size = cl.maxclients;
7835                         if (r_qwskincache)
7836                                 Mem_Free(r_qwskincache);
7837                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7838                 }
7839                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7840                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7841                 t->currentskinframe = r_qwskincache[i].skinframe;
7842                 if (t->currentskinframe == NULL)
7843                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7844         }
7845         else if (t->numskinframes >= 2)
7846                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7847         if (t->backgroundnumskinframes >= 2)
7848                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7849
7850         t->currentmaterialflags = t->basematerialflags;
7851         t->currentalpha = rsurface.colormod[3];
7852         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7853                 t->currentalpha *= r_wateralpha.value;
7854         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7855                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7856         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7857                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7858         if (!(rsurface.ent_flags & RENDER_LIGHT))
7859                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7860         else if (FAKELIGHT_ENABLED)
7861         {
7862                 // no modellight if using fakelight for the map
7863         }
7864         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7865         {
7866                 // pick a model lighting mode
7867                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7868                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7869                 else
7870                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7871         }
7872         if (rsurface.ent_flags & RENDER_ADDITIVE)
7873                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7874         else if (t->currentalpha < 1)
7875                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7876         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7877         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7878                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7879         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7880                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7881         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7882                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7883         if (t->backgroundnumskinframes)
7884                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7885         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7886         {
7887                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7888                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7889         }
7890         else
7891                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7892         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7893         {
7894                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7895                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7896         }
7897         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7898                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7899
7900         // there is no tcmod
7901         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7902         {
7903                 t->currenttexmatrix = r_waterscrollmatrix;
7904                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7905         }
7906         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7907         {
7908                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7909                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7910         }
7911
7912         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7913                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7914         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7915                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7916
7917         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7918         if (t->currentskinframe->qpixels)
7919                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7920         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7921         if (!t->basetexture)
7922                 t->basetexture = r_texture_notexture;
7923         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7924         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7925         t->nmaptexture = t->currentskinframe->nmap;
7926         if (!t->nmaptexture)
7927                 t->nmaptexture = r_texture_blanknormalmap;
7928         t->glosstexture = r_texture_black;
7929         t->glowtexture = t->currentskinframe->glow;
7930         t->fogtexture = t->currentskinframe->fog;
7931         t->reflectmasktexture = t->currentskinframe->reflect;
7932         if (t->backgroundnumskinframes)
7933         {
7934                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7935                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7936                 t->backgroundglosstexture = r_texture_black;
7937                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7938                 if (!t->backgroundnmaptexture)
7939                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7940         }
7941         else
7942         {
7943                 t->backgroundbasetexture = r_texture_white;
7944                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7945                 t->backgroundglosstexture = r_texture_black;
7946                 t->backgroundglowtexture = NULL;
7947         }
7948         t->specularpower = r_shadow_glossexponent.value;
7949         // TODO: store reference values for these in the texture?
7950         t->specularscale = 0;
7951         if (r_shadow_gloss.integer > 0)
7952         {
7953                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7954                 {
7955                         if (r_shadow_glossintensity.value > 0)
7956                         {
7957                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7958                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7959                                 t->specularscale = r_shadow_glossintensity.value;
7960                         }
7961                 }
7962                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7963                 {
7964                         t->glosstexture = r_texture_white;
7965                         t->backgroundglosstexture = r_texture_white;
7966                         t->specularscale = r_shadow_gloss2intensity.value;
7967                         t->specularpower = r_shadow_gloss2exponent.value;
7968                 }
7969         }
7970         t->specularscale *= t->specularscalemod;
7971         t->specularpower *= t->specularpowermod;
7972         t->rtlightambient = 0;
7973
7974         // lightmaps mode looks bad with dlights using actual texturing, so turn
7975         // off the colormap and glossmap, but leave the normalmap on as it still
7976         // accurately represents the shading involved
7977         if (gl_lightmaps.integer)
7978         {
7979                 t->basetexture = r_texture_grey128;
7980                 t->pantstexture = r_texture_black;
7981                 t->shirttexture = r_texture_black;
7982                 t->nmaptexture = r_texture_blanknormalmap;
7983                 t->glosstexture = r_texture_black;
7984                 t->glowtexture = NULL;
7985                 t->fogtexture = NULL;
7986                 t->reflectmasktexture = NULL;
7987                 t->backgroundbasetexture = NULL;
7988                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7989                 t->backgroundglosstexture = r_texture_black;
7990                 t->backgroundglowtexture = NULL;
7991                 t->specularscale = 0;
7992                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7993         }
7994
7995         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7996         VectorClear(t->dlightcolor);
7997         t->currentnumlayers = 0;
7998         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7999         {
8000                 int blendfunc1, blendfunc2;
8001                 qboolean depthmask;
8002                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8003                 {
8004                         blendfunc1 = GL_SRC_ALPHA;
8005                         blendfunc2 = GL_ONE;
8006                 }
8007                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8008                 {
8009                         blendfunc1 = GL_SRC_ALPHA;
8010                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8011                 }
8012                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8013                 {
8014                         blendfunc1 = t->customblendfunc[0];
8015                         blendfunc2 = t->customblendfunc[1];
8016                 }
8017                 else
8018                 {
8019                         blendfunc1 = GL_ONE;
8020                         blendfunc2 = GL_ZERO;
8021                 }
8022                 // don't colormod evilblend textures
8023                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8024                         VectorSet(t->lightmapcolor, 1, 1, 1);
8025                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8026                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8027                 {
8028                         // fullbright is not affected by r_refdef.lightmapintensity
8029                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8030                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8031                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8032                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8033                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8034                 }
8035                 else
8036                 {
8037                         vec3_t ambientcolor;
8038                         float colorscale;
8039                         // set the color tint used for lights affecting this surface
8040                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8041                         colorscale = 2;
8042                         // q3bsp has no lightmap updates, so the lightstylevalue that
8043                         // would normally be baked into the lightmap must be
8044                         // applied to the color
8045                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8046                         if (model->type == mod_brushq3)
8047                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8048                         colorscale *= r_refdef.lightmapintensity;
8049                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8050                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8051                         // basic lit geometry
8052                         R_Texture_AddLayer(t, depthmask, blendfunc1, blendfunc2, TEXTURELAYERTYPE_LITTEXTURE, t->basetexture, &t->currenttexmatrix, t->lightmapcolor[0], t->lightmapcolor[1], t->lightmapcolor[2], t->lightmapcolor[3]);
8053                         // add pants/shirt if needed
8054                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8055                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * t->lightmapcolor[0], rsurface.colormap_pantscolor[1] * t->lightmapcolor[1], rsurface.colormap_pantscolor[2]  * t->lightmapcolor[2], t->lightmapcolor[3]);
8056                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8057                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_LITTEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * t->lightmapcolor[0], rsurface.colormap_shirtcolor[1] * t->lightmapcolor[1], rsurface.colormap_shirtcolor[2] * t->lightmapcolor[2], t->lightmapcolor[3]);
8058                         // now add ambient passes if needed
8059                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8060                         {
8061                                 R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->basetexture, &t->currenttexmatrix, ambientcolor[0], ambientcolor[1], ambientcolor[2], t->lightmapcolor[3]);
8062                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8063                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8064                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8065                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8066                         }
8067                 }
8068                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8069                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->glowtexture, &t->currenttexmatrix, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2], t->lightmapcolor[3]);
8070                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8071                 {
8072                         // if this is opaque use alpha blend which will darken the earlier
8073                         // passes cheaply.
8074                         //
8075                         // if this is an alpha blended material, all the earlier passes
8076                         // were darkened by fog already, so we only need to add the fog
8077                         // color ontop through the fog mask texture
8078                         //
8079                         // if this is an additive blended material, all the earlier passes
8080                         // were darkened by fog already, and we should not add fog color
8081                         // (because the background was not darkened, there is no fog color
8082                         // that was lost behind it).
8083                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, (t->currentmaterialflags & MATERIALFLAG_BLENDED) ? GL_ONE : GL_ONE_MINUS_SRC_ALPHA, TEXTURELAYERTYPE_FOG, t->fogtexture, &t->currenttexmatrix, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], t->lightmapcolor[3]);
8084                 }
8085         }
8086
8087         return t->currentframe;
8088 }
8089
8090 rsurfacestate_t rsurface;
8091
8092 void RSurf_ActiveWorldEntity(void)
8093 {
8094         dp_model_t *model = r_refdef.scene.worldmodel;
8095         //if (rsurface.entity == r_refdef.scene.worldentity)
8096         //      return;
8097         rsurface.entity = r_refdef.scene.worldentity;
8098         rsurface.skeleton = NULL;
8099         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8100         rsurface.ent_skinnum = 0;
8101         rsurface.ent_qwskin = -1;
8102         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8103         rsurface.shadertime = r_refdef.scene.time;
8104         rsurface.matrix = identitymatrix;
8105         rsurface.inversematrix = identitymatrix;
8106         rsurface.matrixscale = 1;
8107         rsurface.inversematrixscale = 1;
8108         R_EntityMatrix(&identitymatrix);
8109         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8110         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8111         rsurface.fograngerecip = r_refdef.fograngerecip;
8112         rsurface.fogheightfade = r_refdef.fogheightfade;
8113         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8114         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8115         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8116         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8117         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8118         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8119         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8120         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8121         rsurface.colormod[3] = 1;
8122         VectorSet(rsurface.glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value, r_refdef.view.colorscale * r_hdr_glowintensity.value);
8123         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8124         rsurface.frameblend[0].lerp = 1;
8125         rsurface.ent_alttextures = false;
8126         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8127         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8128         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8129         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8130         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8131         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8132         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8133         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8134         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8135         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8136         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8137         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8138         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8139         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8140         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8141         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8143         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8144         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8146         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8147         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8148         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8149         rsurface.modelelement3i = model->surfmesh.data_element3i;
8150         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8151         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8152         rsurface.modelelement3s = model->surfmesh.data_element3s;
8153         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8154         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8155         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8156         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8157         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8158         rsurface.modelsurfaces = model->data_surfaces;
8159         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8160         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8161         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8162         rsurface.modelgeneratedvertex = false;
8163         rsurface.batchgeneratedvertex = false;
8164         rsurface.batchfirstvertex = 0;
8165         rsurface.batchnumvertices = 0;
8166         rsurface.batchfirsttriangle = 0;
8167         rsurface.batchnumtriangles = 0;
8168         rsurface.batchvertex3f  = NULL;
8169         rsurface.batchvertex3f_vertexbuffer = NULL;
8170         rsurface.batchvertex3f_bufferoffset = 0;
8171         rsurface.batchsvector3f = NULL;
8172         rsurface.batchsvector3f_vertexbuffer = NULL;
8173         rsurface.batchsvector3f_bufferoffset = 0;
8174         rsurface.batchtvector3f = NULL;
8175         rsurface.batchtvector3f_vertexbuffer = NULL;
8176         rsurface.batchtvector3f_bufferoffset = 0;
8177         rsurface.batchnormal3f  = NULL;
8178         rsurface.batchnormal3f_vertexbuffer = NULL;
8179         rsurface.batchnormal3f_bufferoffset = 0;
8180         rsurface.batchlightmapcolor4f = NULL;
8181         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8182         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8183         rsurface.batchtexcoordtexture2f = NULL;
8184         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8185         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8186         rsurface.batchtexcoordlightmap2f = NULL;
8187         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8188         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8189         rsurface.batchvertexmesh = NULL;
8190         rsurface.batchvertexmeshbuffer = NULL;
8191         rsurface.batchvertex3fbuffer = NULL;
8192         rsurface.batchelement3i = NULL;
8193         rsurface.batchelement3i_indexbuffer = NULL;
8194         rsurface.batchelement3i_bufferoffset = 0;
8195         rsurface.batchelement3s = NULL;
8196         rsurface.batchelement3s_indexbuffer = NULL;
8197         rsurface.batchelement3s_bufferoffset = 0;
8198         rsurface.passcolor4f = NULL;
8199         rsurface.passcolor4f_vertexbuffer = NULL;
8200         rsurface.passcolor4f_bufferoffset = 0;
8201 }
8202
8203 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8204 {
8205         dp_model_t *model = ent->model;
8206         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8207         //      return;
8208         rsurface.entity = (entity_render_t *)ent;
8209         rsurface.skeleton = ent->skeleton;
8210         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8211         rsurface.ent_skinnum = ent->skinnum;
8212         rsurface.ent_qwskin = (ent->entitynumber <= cl.maxclients && ent->entitynumber >= 1 && cls.protocol == PROTOCOL_QUAKEWORLD && cl.scores[ent->entitynumber - 1].qw_skin[0] && !strcmp(ent->model->name, "progs/player.mdl")) ? (ent->entitynumber - 1) : -1;
8213         rsurface.ent_flags = ent->flags;
8214         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8215         rsurface.matrix = ent->matrix;
8216         rsurface.inversematrix = ent->inversematrix;
8217         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8218         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8219         R_EntityMatrix(&rsurface.matrix);
8220         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8221         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8222         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8223         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8224         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8225         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8226         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8227         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8228         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8229         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8230         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8231         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8232         rsurface.colormod[3] = ent->alpha;
8233         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8234         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8235         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8236         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8237         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8238         if (ent->model->brush.submodel && !prepass)
8239         {
8240                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8241                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8242         }
8243         if (model->surfmesh.isanimated && model->AnimateVertices)
8244         {
8245                 if (ent->animcache_vertex3f)
8246                 {
8247                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8248                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8249                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8250                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8251                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8252                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8253                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8254                 }
8255                 else if (wanttangents)
8256                 {
8257                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8258                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8261                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8262                         rsurface.modelvertexmesh = NULL;
8263                         rsurface.modelvertexmeshbuffer = NULL;
8264                         rsurface.modelvertex3fbuffer = NULL;
8265                 }
8266                 else if (wantnormals)
8267                 {
8268                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8269                         rsurface.modelsvector3f = NULL;
8270                         rsurface.modeltvector3f = NULL;
8271                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8272                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8273                         rsurface.modelvertexmesh = NULL;
8274                         rsurface.modelvertexmeshbuffer = NULL;
8275                         rsurface.modelvertex3fbuffer = NULL;
8276                 }
8277                 else
8278                 {
8279                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8280                         rsurface.modelsvector3f = NULL;
8281                         rsurface.modeltvector3f = NULL;
8282                         rsurface.modelnormal3f = NULL;
8283                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8284                         rsurface.modelvertexmesh = NULL;
8285                         rsurface.modelvertexmeshbuffer = NULL;
8286                         rsurface.modelvertex3fbuffer = NULL;
8287                 }
8288                 rsurface.modelvertex3f_vertexbuffer = 0;
8289                 rsurface.modelvertex3f_bufferoffset = 0;
8290                 rsurface.modelsvector3f_vertexbuffer = 0;
8291                 rsurface.modelsvector3f_bufferoffset = 0;
8292                 rsurface.modeltvector3f_vertexbuffer = 0;
8293                 rsurface.modeltvector3f_bufferoffset = 0;
8294                 rsurface.modelnormal3f_vertexbuffer = 0;
8295                 rsurface.modelnormal3f_bufferoffset = 0;
8296                 rsurface.modelgeneratedvertex = true;
8297         }
8298         else
8299         {
8300                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8301                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8303                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8304                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8306                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8307                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8308                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8309                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8310                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8311                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8312                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8313                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8314                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8315                 rsurface.modelgeneratedvertex = false;
8316         }
8317         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8318         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8319         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8320         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8321         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8322         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8323         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8324         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8325         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8326         rsurface.modelelement3i = model->surfmesh.data_element3i;
8327         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8328         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8329         rsurface.modelelement3s = model->surfmesh.data_element3s;
8330         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8331         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8332         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8333         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8334         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8335         rsurface.modelsurfaces = model->data_surfaces;
8336         rsurface.batchgeneratedvertex = false;
8337         rsurface.batchfirstvertex = 0;
8338         rsurface.batchnumvertices = 0;
8339         rsurface.batchfirsttriangle = 0;
8340         rsurface.batchnumtriangles = 0;
8341         rsurface.batchvertex3f  = NULL;
8342         rsurface.batchvertex3f_vertexbuffer = NULL;
8343         rsurface.batchvertex3f_bufferoffset = 0;
8344         rsurface.batchsvector3f = NULL;
8345         rsurface.batchsvector3f_vertexbuffer = NULL;
8346         rsurface.batchsvector3f_bufferoffset = 0;
8347         rsurface.batchtvector3f = NULL;
8348         rsurface.batchtvector3f_vertexbuffer = NULL;
8349         rsurface.batchtvector3f_bufferoffset = 0;
8350         rsurface.batchnormal3f  = NULL;
8351         rsurface.batchnormal3f_vertexbuffer = NULL;
8352         rsurface.batchnormal3f_bufferoffset = 0;
8353         rsurface.batchlightmapcolor4f = NULL;
8354         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8355         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8356         rsurface.batchtexcoordtexture2f = NULL;
8357         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8358         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8359         rsurface.batchtexcoordlightmap2f = NULL;
8360         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8361         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8362         rsurface.batchvertexmesh = NULL;
8363         rsurface.batchvertexmeshbuffer = NULL;
8364         rsurface.batchvertex3fbuffer = NULL;
8365         rsurface.batchelement3i = NULL;
8366         rsurface.batchelement3i_indexbuffer = NULL;
8367         rsurface.batchelement3i_bufferoffset = 0;
8368         rsurface.batchelement3s = NULL;
8369         rsurface.batchelement3s_indexbuffer = NULL;
8370         rsurface.batchelement3s_bufferoffset = 0;
8371         rsurface.passcolor4f = NULL;
8372         rsurface.passcolor4f_vertexbuffer = NULL;
8373         rsurface.passcolor4f_bufferoffset = 0;
8374 }
8375
8376 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)
8377 {
8378         rsurface.entity = r_refdef.scene.worldentity;
8379         rsurface.skeleton = NULL;
8380         rsurface.ent_skinnum = 0;
8381         rsurface.ent_qwskin = -1;
8382         rsurface.ent_flags = entflags;
8383         rsurface.shadertime = r_refdef.scene.time - shadertime;
8384         rsurface.modelnumvertices = numvertices;
8385         rsurface.modelnumtriangles = numtriangles;
8386         rsurface.matrix = *matrix;
8387         rsurface.inversematrix = *inversematrix;
8388         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8389         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8390         R_EntityMatrix(&rsurface.matrix);
8391         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8392         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8393         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8394         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8395         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8396         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8397         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8398         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8399         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8400         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8401         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8402         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8403         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);
8404         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8405         rsurface.frameblend[0].lerp = 1;
8406         rsurface.ent_alttextures = false;
8407         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8408         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8409         if (wanttangents)
8410         {
8411                 rsurface.modelvertex3f = (float *)vertex3f;
8412                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8413                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8414                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8415         }
8416         else if (wantnormals)
8417         {
8418                 rsurface.modelvertex3f = (float *)vertex3f;
8419                 rsurface.modelsvector3f = NULL;
8420                 rsurface.modeltvector3f = NULL;
8421                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8422         }
8423         else
8424         {
8425                 rsurface.modelvertex3f = (float *)vertex3f;
8426                 rsurface.modelsvector3f = NULL;
8427                 rsurface.modeltvector3f = NULL;
8428                 rsurface.modelnormal3f = NULL;
8429         }
8430         rsurface.modelvertexmesh = NULL;
8431         rsurface.modelvertexmeshbuffer = NULL;
8432         rsurface.modelvertex3fbuffer = NULL;
8433         rsurface.modelvertex3f_vertexbuffer = 0;
8434         rsurface.modelvertex3f_bufferoffset = 0;
8435         rsurface.modelsvector3f_vertexbuffer = 0;
8436         rsurface.modelsvector3f_bufferoffset = 0;
8437         rsurface.modeltvector3f_vertexbuffer = 0;
8438         rsurface.modeltvector3f_bufferoffset = 0;
8439         rsurface.modelnormal3f_vertexbuffer = 0;
8440         rsurface.modelnormal3f_bufferoffset = 0;
8441         rsurface.modelgeneratedvertex = true;
8442         rsurface.modellightmapcolor4f  = (float *)color4f;
8443         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8444         rsurface.modellightmapcolor4f_bufferoffset = 0;
8445         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8446         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8447         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8448         rsurface.modeltexcoordlightmap2f  = NULL;
8449         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8450         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8451         rsurface.modelelement3i = (int *)element3i;
8452         rsurface.modelelement3i_indexbuffer = NULL;
8453         rsurface.modelelement3i_bufferoffset = 0;
8454         rsurface.modelelement3s = (unsigned short *)element3s;
8455         rsurface.modelelement3s_indexbuffer = NULL;
8456         rsurface.modelelement3s_bufferoffset = 0;
8457         rsurface.modellightmapoffsets = NULL;
8458         rsurface.modelsurfaces = NULL;
8459         rsurface.batchgeneratedvertex = false;
8460         rsurface.batchfirstvertex = 0;
8461         rsurface.batchnumvertices = 0;
8462         rsurface.batchfirsttriangle = 0;
8463         rsurface.batchnumtriangles = 0;
8464         rsurface.batchvertex3f  = NULL;
8465         rsurface.batchvertex3f_vertexbuffer = NULL;
8466         rsurface.batchvertex3f_bufferoffset = 0;
8467         rsurface.batchsvector3f = NULL;
8468         rsurface.batchsvector3f_vertexbuffer = NULL;
8469         rsurface.batchsvector3f_bufferoffset = 0;
8470         rsurface.batchtvector3f = NULL;
8471         rsurface.batchtvector3f_vertexbuffer = NULL;
8472         rsurface.batchtvector3f_bufferoffset = 0;
8473         rsurface.batchnormal3f  = NULL;
8474         rsurface.batchnormal3f_vertexbuffer = NULL;
8475         rsurface.batchnormal3f_bufferoffset = 0;
8476         rsurface.batchlightmapcolor4f = NULL;
8477         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8478         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8479         rsurface.batchtexcoordtexture2f = NULL;
8480         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8481         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8482         rsurface.batchtexcoordlightmap2f = NULL;
8483         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8484         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8485         rsurface.batchvertexmesh = NULL;
8486         rsurface.batchvertexmeshbuffer = NULL;
8487         rsurface.batchvertex3fbuffer = NULL;
8488         rsurface.batchelement3i = NULL;
8489         rsurface.batchelement3i_indexbuffer = NULL;
8490         rsurface.batchelement3i_bufferoffset = 0;
8491         rsurface.batchelement3s = NULL;
8492         rsurface.batchelement3s_indexbuffer = NULL;
8493         rsurface.batchelement3s_bufferoffset = 0;
8494         rsurface.passcolor4f = NULL;
8495         rsurface.passcolor4f_vertexbuffer = NULL;
8496         rsurface.passcolor4f_bufferoffset = 0;
8497
8498         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8499         {
8500                 if ((wantnormals || wanttangents) && !normal3f)
8501                 {
8502                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8503                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8504                 }
8505                 if (wanttangents && !svector3f)
8506                 {
8507                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8508                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8509                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8510                 }
8511         }
8512 }
8513
8514 float RSurf_FogPoint(const float *v)
8515 {
8516         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8517         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8518         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8519         float FogHeightFade = r_refdef.fogheightfade;
8520         float fogfrac;
8521         unsigned int fogmasktableindex;
8522         if (r_refdef.fogplaneviewabove)
8523                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8524         else
8525                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8526         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8527         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8528 }
8529
8530 float RSurf_FogVertex(const float *v)
8531 {
8532         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8533         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8534         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8535         float FogHeightFade = rsurface.fogheightfade;
8536         float fogfrac;
8537         unsigned int fogmasktableindex;
8538         if (r_refdef.fogplaneviewabove)
8539                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8540         else
8541                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8542         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8543         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8544 }
8545
8546 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8547 {
8548         int i;
8549         for (i = 0;i < numelements;i++)
8550                 outelement3i[i] = inelement3i[i] + adjust;
8551 }
8552
8553 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8554 extern cvar_t gl_vbo;
8555 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8556 {
8557         int deformindex;
8558         int firsttriangle;
8559         int numtriangles;
8560         int firstvertex;
8561         int endvertex;
8562         int numvertices;
8563         int surfacefirsttriangle;
8564         int surfacenumtriangles;
8565         int surfacefirstvertex;
8566         int surfaceendvertex;
8567         int surfacenumvertices;
8568         int batchnumvertices;
8569         int batchnumtriangles;
8570         int needsupdate;
8571         int i, j;
8572         qboolean gaps;
8573         qboolean dynamicvertex;
8574         float amplitude;
8575         float animpos;
8576         float scale;
8577         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8578         float waveparms[4];
8579         q3shaderinfo_deform_t *deform;
8580         const msurface_t *surface, *firstsurface;
8581         r_vertexmesh_t *vertexmesh;
8582         if (!texturenumsurfaces)
8583                 return;
8584         // find vertex range of this surface batch
8585         gaps = false;
8586         firstsurface = texturesurfacelist[0];
8587         firsttriangle = firstsurface->num_firsttriangle;
8588         batchnumvertices = 0;
8589         batchnumtriangles = 0;
8590         firstvertex = endvertex = firstsurface->num_firstvertex;
8591         for (i = 0;i < texturenumsurfaces;i++)
8592         {
8593                 surface = texturesurfacelist[i];
8594                 if (surface != firstsurface + i)
8595                         gaps = true;
8596                 surfacefirstvertex = surface->num_firstvertex;
8597                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8598                 surfacenumvertices = surface->num_vertices;
8599                 surfacenumtriangles = surface->num_triangles;
8600                 if (firstvertex > surfacefirstvertex)
8601                         firstvertex = surfacefirstvertex;
8602                 if (endvertex < surfaceendvertex)
8603                         endvertex = surfaceendvertex;
8604                 batchnumvertices += surfacenumvertices;
8605                 batchnumtriangles += surfacenumtriangles;
8606         }
8607
8608         // we now know the vertex range used, and if there are any gaps in it
8609         rsurface.batchfirstvertex = firstvertex;
8610         rsurface.batchnumvertices = endvertex - firstvertex;
8611         rsurface.batchfirsttriangle = firsttriangle;
8612         rsurface.batchnumtriangles = batchnumtriangles;
8613
8614         // this variable holds flags for which properties have been updated that
8615         // may require regenerating vertexmesh array...
8616         needsupdate = 0;
8617
8618         // check if any dynamic vertex processing must occur
8619         dynamicvertex = false;
8620
8621         // if there is a chance of animated vertex colors, it's a dynamic batch
8622         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8623         {
8624                 dynamicvertex = true;
8625                 batchneed |= BATCHNEED_NOGAPS;
8626                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8627         }
8628
8629         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8630         {
8631                 switch (deform->deform)
8632                 {
8633                 default:
8634                 case Q3DEFORM_PROJECTIONSHADOW:
8635                 case Q3DEFORM_TEXT0:
8636                 case Q3DEFORM_TEXT1:
8637                 case Q3DEFORM_TEXT2:
8638                 case Q3DEFORM_TEXT3:
8639                 case Q3DEFORM_TEXT4:
8640                 case Q3DEFORM_TEXT5:
8641                 case Q3DEFORM_TEXT6:
8642                 case Q3DEFORM_TEXT7:
8643                 case Q3DEFORM_NONE:
8644                         break;
8645                 case Q3DEFORM_AUTOSPRITE:
8646                         dynamicvertex = true;
8647                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8648                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8649                         break;
8650                 case Q3DEFORM_AUTOSPRITE2:
8651                         dynamicvertex = true;
8652                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8653                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8654                         break;
8655                 case Q3DEFORM_NORMAL:
8656                         dynamicvertex = true;
8657                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8658                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8659                         break;
8660                 case Q3DEFORM_WAVE:
8661                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8662                                 break; // if wavefunc is a nop, ignore this transform
8663                         dynamicvertex = true;
8664                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8665                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8666                         break;
8667                 case Q3DEFORM_BULGE:
8668                         dynamicvertex = true;
8669                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8670                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8671                         break;
8672                 case Q3DEFORM_MOVE:
8673                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8674                                 break; // if wavefunc is a nop, ignore this transform
8675                         dynamicvertex = true;
8676                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8677                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8678                         break;
8679                 }
8680         }
8681         switch(rsurface.texture->tcgen.tcgen)
8682         {
8683         default:
8684         case Q3TCGEN_TEXTURE:
8685                 break;
8686         case Q3TCGEN_LIGHTMAP:
8687                 dynamicvertex = true;
8688                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8689                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8690                 break;
8691         case Q3TCGEN_VECTOR:
8692                 dynamicvertex = true;
8693                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8694                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8695                 break;
8696         case Q3TCGEN_ENVIRONMENT:
8697                 dynamicvertex = true;
8698                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8699                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8700                 break;
8701         }
8702         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8703         {
8704                 dynamicvertex = true;
8705                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8706                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8707         }
8708
8709         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8710         {
8711                 dynamicvertex = true;
8712                 batchneed |= BATCHNEED_NOGAPS;
8713                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8714         }
8715
8716         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8717         {
8718                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8719                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8721                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8723                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8724                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8725         }
8726
8727         // when the model data has no vertex buffer (dynamic mesh), we need to
8728         // eliminate gaps
8729         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8730                 batchneed |= BATCHNEED_NOGAPS;
8731
8732         // if needsupdate, we have to do a dynamic vertex batch for sure
8733         if (needsupdate & batchneed)
8734                 dynamicvertex = true;
8735
8736         // see if we need to build vertexmesh from arrays
8737         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8738                 dynamicvertex = true;
8739
8740         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8741         // also some drivers strongly dislike firstvertex
8742         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8743                 dynamicvertex = true;
8744
8745         rsurface.batchvertex3f = rsurface.modelvertex3f;
8746         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8747         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8748         rsurface.batchsvector3f = rsurface.modelsvector3f;
8749         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8750         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8751         rsurface.batchtvector3f = rsurface.modeltvector3f;
8752         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8753         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8754         rsurface.batchnormal3f = rsurface.modelnormal3f;
8755         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8756         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8757         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8758         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8759         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8760         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8761         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8762         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8763         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8764         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8765         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8766         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8767         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8768         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8769         rsurface.batchelement3i = rsurface.modelelement3i;
8770         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8771         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8772         rsurface.batchelement3s = rsurface.modelelement3s;
8773         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8774         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8775
8776         // if any dynamic vertex processing has to occur in software, we copy the
8777         // entire surface list together before processing to rebase the vertices
8778         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8779         //
8780         // if any gaps exist and we do not have a static vertex buffer, we have to
8781         // copy the surface list together to avoid wasting upload bandwidth on the
8782         // vertices in the gaps.
8783         //
8784         // if gaps exist and we have a static vertex buffer, we still have to
8785         // combine the index buffer ranges into one dynamic index buffer.
8786         //
8787         // in all cases we end up with data that can be drawn in one call.
8788
8789         if (!dynamicvertex)
8790         {
8791                 // static vertex data, just set pointers...
8792                 rsurface.batchgeneratedvertex = false;
8793                 // if there are gaps, we want to build a combined index buffer,
8794                 // otherwise use the original static buffer with an appropriate offset
8795                 if (gaps)
8796                 {
8797                         // build a new triangle elements array for this batch
8798                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8799                         rsurface.batchfirsttriangle = 0;
8800                         numtriangles = 0;
8801                         for (i = 0;i < texturenumsurfaces;i++)
8802                         {
8803                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8804                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8805                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8806                                 numtriangles += surfacenumtriangles;
8807                         }
8808                         rsurface.batchelement3i_indexbuffer = NULL;
8809                         rsurface.batchelement3i_bufferoffset = 0;
8810                         rsurface.batchelement3s = NULL;
8811                         rsurface.batchelement3s_indexbuffer = NULL;
8812                         rsurface.batchelement3s_bufferoffset = 0;
8813                         if (endvertex <= 65536)
8814                         {
8815                                 // make a 16bit (unsigned short) index array if possible
8816                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8817                                 for (i = 0;i < numtriangles*3;i++)
8818                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8819                         }
8820                 }
8821                 return;
8822         }
8823
8824         // something needs software processing, do it for real...
8825         // we only directly handle separate array data in this case and then
8826         // generate interleaved data if needed...
8827         rsurface.batchgeneratedvertex = true;
8828
8829         // now copy the vertex data into a combined array and make an index array
8830         // (this is what Quake3 does all the time)
8831         //if (gaps || rsurface.batchfirstvertex)
8832         {
8833                 rsurface.batchvertex3fbuffer = NULL;
8834                 rsurface.batchvertexmesh = NULL;
8835                 rsurface.batchvertexmeshbuffer = NULL;
8836                 rsurface.batchvertex3f = NULL;
8837                 rsurface.batchvertex3f_vertexbuffer = NULL;
8838                 rsurface.batchvertex3f_bufferoffset = 0;
8839                 rsurface.batchsvector3f = NULL;
8840                 rsurface.batchsvector3f_vertexbuffer = NULL;
8841                 rsurface.batchsvector3f_bufferoffset = 0;
8842                 rsurface.batchtvector3f = NULL;
8843                 rsurface.batchtvector3f_vertexbuffer = NULL;
8844                 rsurface.batchtvector3f_bufferoffset = 0;
8845                 rsurface.batchnormal3f = NULL;
8846                 rsurface.batchnormal3f_vertexbuffer = NULL;
8847                 rsurface.batchnormal3f_bufferoffset = 0;
8848                 rsurface.batchlightmapcolor4f = NULL;
8849                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8850                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8851                 rsurface.batchtexcoordtexture2f = NULL;
8852                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8853                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8854                 rsurface.batchtexcoordlightmap2f = NULL;
8855                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8856                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8857                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8858                 rsurface.batchelement3i_indexbuffer = NULL;
8859                 rsurface.batchelement3i_bufferoffset = 0;
8860                 rsurface.batchelement3s = NULL;
8861                 rsurface.batchelement3s_indexbuffer = NULL;
8862                 rsurface.batchelement3s_bufferoffset = 0;
8863                 // we'll only be setting up certain arrays as needed
8864                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8865                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8866                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8867                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8869                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8871                 {
8872                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8873                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8874                 }
8875                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8876                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8877                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8878                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8879                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8880                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8881                 numvertices = 0;
8882                 numtriangles = 0;
8883                 for (i = 0;i < texturenumsurfaces;i++)
8884                 {
8885                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8886                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8887                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8888                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8889                         // copy only the data requested
8890                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8891                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8892                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8893                         {
8894                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8895                                 {
8896                                         if (rsurface.batchvertex3f)
8897                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8898                                         else
8899                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8900                                 }
8901                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8902                                 {
8903                                         if (rsurface.modelnormal3f)
8904                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8905                                         else
8906                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8907                                 }
8908                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8909                                 {
8910                                         if (rsurface.modelsvector3f)
8911                                         {
8912                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8913                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8914                                         }
8915                                         else
8916                                         {
8917                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8918                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8919                                         }
8920                                 }
8921                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8922                                 {
8923                                         if (rsurface.modellightmapcolor4f)
8924                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8925                                         else
8926                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8927                                 }
8928                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8929                                 {
8930                                         if (rsurface.modeltexcoordtexture2f)
8931                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8932                                         else
8933                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8934                                 }
8935                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8936                                 {
8937                                         if (rsurface.modeltexcoordlightmap2f)
8938                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8939                                         else
8940                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8941                                 }
8942                         }
8943                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8944                         numvertices += surfacenumvertices;
8945                         numtriangles += surfacenumtriangles;
8946                 }
8947
8948                 // generate a 16bit index array as well if possible
8949                 // (in general, dynamic batches fit)
8950                 if (numvertices <= 65536)
8951                 {
8952                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8953                         for (i = 0;i < numtriangles*3;i++)
8954                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8955                 }
8956
8957                 // since we've copied everything, the batch now starts at 0
8958                 rsurface.batchfirstvertex = 0;
8959                 rsurface.batchnumvertices = batchnumvertices;
8960                 rsurface.batchfirsttriangle = 0;
8961                 rsurface.batchnumtriangles = batchnumtriangles;
8962         }
8963
8964         // q1bsp surfaces rendered in vertex color mode have to have colors
8965         // calculated based on lightstyles
8966         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8967         {
8968                 // generate color arrays for the surfaces in this list
8969                 int c[4];
8970                 int scale;
8971                 int size3;
8972                 const int *offsets;
8973                 const unsigned char *lm;
8974                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8975                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8976                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8977                 numvertices = 0;
8978                 for (i = 0;i < texturenumsurfaces;i++)
8979                 {
8980                         surface = texturesurfacelist[i];
8981                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8982                         surfacenumvertices = surface->num_vertices;
8983                         if (surface->lightmapinfo->samples)
8984                         {
8985                                 for (j = 0;j < surfacenumvertices;j++)
8986                                 {
8987                                         lm = surface->lightmapinfo->samples + offsets[j];
8988                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8989                                         VectorScale(lm, scale, c);
8990                                         if (surface->lightmapinfo->styles[1] != 255)
8991                                         {
8992                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8993                                                 lm += size3;
8994                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8995                                                 VectorMA(c, scale, lm, c);
8996                                                 if (surface->lightmapinfo->styles[2] != 255)
8997                                                 {
8998                                                         lm += size3;
8999                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9000                                                         VectorMA(c, scale, lm, c);
9001                                                         if (surface->lightmapinfo->styles[3] != 255)
9002                                                         {
9003                                                                 lm += size3;
9004                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9005                                                                 VectorMA(c, scale, lm, c);
9006                                                         }
9007                                                 }
9008                                         }
9009                                         c[0] >>= 7;
9010                                         c[1] >>= 7;
9011                                         c[2] >>= 7;
9012                                         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);
9013                                         numvertices++;
9014                                 }
9015                         }
9016                         else
9017                         {
9018                                 for (j = 0;j < surfacenumvertices;j++)
9019                                 {
9020                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9021                                         numvertices++;
9022                                 }
9023                         }
9024                 }
9025         }
9026
9027         // if vertices are deformed (sprite flares and things in maps, possibly
9028         // water waves, bulges and other deformations), modify the copied vertices
9029         // in place
9030         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9031         {
9032                 switch (deform->deform)
9033                 {
9034                 default:
9035                 case Q3DEFORM_PROJECTIONSHADOW:
9036                 case Q3DEFORM_TEXT0:
9037                 case Q3DEFORM_TEXT1:
9038                 case Q3DEFORM_TEXT2:
9039                 case Q3DEFORM_TEXT3:
9040                 case Q3DEFORM_TEXT4:
9041                 case Q3DEFORM_TEXT5:
9042                 case Q3DEFORM_TEXT6:
9043                 case Q3DEFORM_TEXT7:
9044                 case Q3DEFORM_NONE:
9045                         break;
9046                 case Q3DEFORM_AUTOSPRITE:
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9048                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9049                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9050                         VectorNormalize(newforward);
9051                         VectorNormalize(newright);
9052                         VectorNormalize(newup);
9053 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9054 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9055 //                      rsurface.batchvertex3f_bufferoffset = 0;
9056 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9057 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9058 //                      rsurface.batchsvector3f_bufferoffset = 0;
9059 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9060 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9061 //                      rsurface.batchtvector3f_bufferoffset = 0;
9062 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9063 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9064 //                      rsurface.batchnormal3f_bufferoffset = 0;
9065                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9066                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9067                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9068                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9069                                 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);
9070                         // a single autosprite surface can contain multiple sprites...
9071                         for (j = 0;j < batchnumvertices - 3;j += 4)
9072                         {
9073                                 VectorClear(center);
9074                                 for (i = 0;i < 4;i++)
9075                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9076                                 VectorScale(center, 0.25f, center);
9077                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9078                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9079                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9080                                 for (i = 0;i < 4;i++)
9081                                 {
9082                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9083                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9084                                 }
9085                         }
9086                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9087                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9088                         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);
9089                         break;
9090                 case Q3DEFORM_AUTOSPRITE2:
9091                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9092                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9093                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9094                         VectorNormalize(newforward);
9095                         VectorNormalize(newright);
9096                         VectorNormalize(newup);
9097 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9098 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9099 //                      rsurface.batchvertex3f_bufferoffset = 0;
9100                         {
9101                                 const float *v1, *v2;
9102                                 vec3_t start, end;
9103                                 float f, l;
9104                                 struct
9105                                 {
9106                                         float length2;
9107                                         const float *v1;
9108                                         const float *v2;
9109                                 }
9110                                 shortest[2];
9111                                 memset(shortest, 0, sizeof(shortest));
9112                                 // a single autosprite surface can contain multiple sprites...
9113                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9114                                 {
9115                                         VectorClear(center);
9116                                         for (i = 0;i < 4;i++)
9117                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9118                                         VectorScale(center, 0.25f, center);
9119                                         // find the two shortest edges, then use them to define the
9120                                         // axis vectors for rotating around the central axis
9121                                         for (i = 0;i < 6;i++)
9122                                         {
9123                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9124                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9125                                                 l = VectorDistance2(v1, v2);
9126                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9127                                                 if (v1[2] != v2[2])
9128                                                         l += (1.0f / 1024.0f);
9129                                                 if (shortest[0].length2 > l || i == 0)
9130                                                 {
9131                                                         shortest[1] = shortest[0];
9132                                                         shortest[0].length2 = l;
9133                                                         shortest[0].v1 = v1;
9134                                                         shortest[0].v2 = v2;
9135                                                 }
9136                                                 else if (shortest[1].length2 > l || i == 1)
9137                                                 {
9138                                                         shortest[1].length2 = l;
9139                                                         shortest[1].v1 = v1;
9140                                                         shortest[1].v2 = v2;
9141                                                 }
9142                                         }
9143                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9144                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9145                                         // this calculates the right vector from the shortest edge
9146                                         // and the up vector from the edge midpoints
9147                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9148                                         VectorNormalize(right);
9149                                         VectorSubtract(end, start, up);
9150                                         VectorNormalize(up);
9151                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9152                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9153                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9154                                         VectorNegate(forward, forward);
9155                                         VectorReflect(forward, 0, up, forward);
9156                                         VectorNormalize(forward);
9157                                         CrossProduct(up, forward, newright);
9158                                         VectorNormalize(newright);
9159                                         // rotate the quad around the up axis vector, this is made
9160                                         // especially easy by the fact we know the quad is flat,
9161                                         // so we only have to subtract the center position and
9162                                         // measure distance along the right vector, and then
9163                                         // multiply that by the newright vector and add back the
9164                                         // center position
9165                                         // we also need to subtract the old position to undo the
9166                                         // displacement from the center, which we do with a
9167                                         // DotProduct, the subtraction/addition of center is also
9168                                         // optimized into DotProducts here
9169                                         l = DotProduct(right, center);
9170                                         for (i = 0;i < 4;i++)
9171                                         {
9172                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9173                                                 f = DotProduct(right, v1) - l;
9174                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9175                                         }
9176                                 }
9177                         }
9178                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9179                         {
9180 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9181 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9182 //                              rsurface.batchnormal3f_bufferoffset = 0;
9183                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9184                         }
9185                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9186                         {
9187 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9188 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9189 //                              rsurface.batchsvector3f_bufferoffset = 0;
9190 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchtvector3f_bufferoffset = 0;
9193                                 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);
9194                         }
9195                         break;
9196                 case Q3DEFORM_NORMAL:
9197                         // deform the normals to make reflections wavey
9198                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9199                         rsurface.batchnormal3f_vertexbuffer = NULL;
9200                         rsurface.batchnormal3f_bufferoffset = 0;
9201                         for (j = 0;j < batchnumvertices;j++)
9202                         {
9203                                 float vertex[3];
9204                                 float *normal = rsurface.batchnormal3f + 3*j;
9205                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9206                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9207                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9208                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9209                                 VectorNormalize(normal);
9210                         }
9211                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9212                         {
9213 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9214 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9215 //                              rsurface.batchsvector3f_bufferoffset = 0;
9216 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9218 //                              rsurface.batchtvector3f_bufferoffset = 0;
9219                                 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);
9220                         }
9221                         break;
9222                 case Q3DEFORM_WAVE:
9223                         // deform vertex array to make wavey water and flags and such
9224                         waveparms[0] = deform->waveparms[0];
9225                         waveparms[1] = deform->waveparms[1];
9226                         waveparms[2] = deform->waveparms[2];
9227                         waveparms[3] = deform->waveparms[3];
9228                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9229                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9230                         // this is how a divisor of vertex influence on deformation
9231                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9232                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9233 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9234 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9235 //                      rsurface.batchvertex3f_bufferoffset = 0;
9236 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9237 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9238 //                      rsurface.batchnormal3f_bufferoffset = 0;
9239                         for (j = 0;j < batchnumvertices;j++)
9240                         {
9241                                 // if the wavefunc depends on time, evaluate it per-vertex
9242                                 if (waveparms[3])
9243                                 {
9244                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9245                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9246                                 }
9247                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9248                         }
9249                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9250                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9251                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9252                         {
9253 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9254 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9255 //                              rsurface.batchsvector3f_bufferoffset = 0;
9256 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9257 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9258 //                              rsurface.batchtvector3f_bufferoffset = 0;
9259                                 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);
9260                         }
9261                         break;
9262                 case Q3DEFORM_BULGE:
9263                         // deform vertex array to make the surface have moving bulges
9264 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9265 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9266 //                      rsurface.batchvertex3f_bufferoffset = 0;
9267 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9268 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9269 //                      rsurface.batchnormal3f_bufferoffset = 0;
9270                         for (j = 0;j < batchnumvertices;j++)
9271                         {
9272                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9273                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9274                         }
9275                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9276                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9277                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9278                         {
9279 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9280 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9281 //                              rsurface.batchsvector3f_bufferoffset = 0;
9282 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9283 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9284 //                              rsurface.batchtvector3f_bufferoffset = 0;
9285                                 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);
9286                         }
9287                         break;
9288                 case Q3DEFORM_MOVE:
9289                         // deform vertex array
9290                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9291                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9292                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9293                         VectorScale(deform->parms, scale, waveparms);
9294 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9295 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9296 //                      rsurface.batchvertex3f_bufferoffset = 0;
9297                         for (j = 0;j < batchnumvertices;j++)
9298                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9299                         break;
9300                 }
9301         }
9302
9303         // generate texcoords based on the chosen texcoord source
9304         switch(rsurface.texture->tcgen.tcgen)
9305         {
9306         default:
9307         case Q3TCGEN_TEXTURE:
9308                 break;
9309         case Q3TCGEN_LIGHTMAP:
9310 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9311 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9312 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9313                 if (rsurface.batchtexcoordlightmap2f)
9314                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9315                 break;
9316         case Q3TCGEN_VECTOR:
9317 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9318 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9319 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9320                 for (j = 0;j < batchnumvertices;j++)
9321                 {
9322                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9323                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9324                 }
9325                 break;
9326         case Q3TCGEN_ENVIRONMENT:
9327                 // make environment reflections using a spheremap
9328                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9329                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9330                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9331                 for (j = 0;j < batchnumvertices;j++)
9332                 {
9333                         // identical to Q3A's method, but executed in worldspace so
9334                         // carried models can be shiny too
9335
9336                         float viewer[3], d, reflected[3], worldreflected[3];
9337
9338                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9339                         // VectorNormalize(viewer);
9340
9341                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9342
9343                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9344                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9345                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9346                         // note: this is proportinal to viewer, so we can normalize later
9347
9348                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9349                         VectorNormalize(worldreflected);
9350
9351                         // note: this sphere map only uses world x and z!
9352                         // so positive and negative y will LOOK THE SAME.
9353                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9354                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9355                 }
9356                 break;
9357         }
9358         // the only tcmod that needs software vertex processing is turbulent, so
9359         // check for it here and apply the changes if needed
9360         // and we only support that as the first one
9361         // (handling a mixture of turbulent and other tcmods would be problematic
9362         //  without punting it entirely to a software path)
9363         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9364         {
9365                 amplitude = rsurface.texture->tcmods[0].parms[1];
9366                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9367 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9368 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9369 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9370                 for (j = 0;j < batchnumvertices;j++)
9371                 {
9372                         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);
9373                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9374                 }
9375         }
9376
9377         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9378         {
9379                 // convert the modified arrays to vertex structs
9380 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9381 //              rsurface.batchvertexmeshbuffer = NULL;
9382                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9383                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9384                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9385                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9386                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9387                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9388                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9389                 {
9390                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9391                         {
9392                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9393                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9394                         }
9395                 }
9396                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9397                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9398                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9399                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9400                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9401                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9402                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9403                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9404                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9405         }
9406 }
9407
9408 void RSurf_DrawBatch(void)
9409 {
9410         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9411         // through the pipeline, killing it earlier in the pipeline would have
9412         // per-surface overhead rather than per-batch overhead, so it's best to
9413         // reject it here, before it hits glDraw.
9414         if (rsurface.batchnumtriangles == 0)
9415                 return;
9416 #if 0
9417         // batch debugging code
9418         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9419         {
9420                 int i;
9421                 int j;
9422                 int c;
9423                 const int *e;
9424                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9425                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9426                 {
9427                         c = e[i];
9428                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9429                         {
9430                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9431                                 {
9432                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9433                                                 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);
9434                                         break;
9435                                 }
9436                         }
9437                 }
9438         }
9439 #endif
9440         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);
9441 }
9442
9443 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9444 {
9445         // pick the closest matching water plane
9446         int planeindex, vertexindex, bestplaneindex = -1;
9447         float d, bestd;
9448         vec3_t vert;
9449         const float *v;
9450         r_waterstate_waterplane_t *p;
9451         qboolean prepared = false;
9452         bestd = 0;
9453         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9454         {
9455                 if(p->camera_entity != rsurface.texture->camera_entity)
9456                         continue;
9457                 d = 0;
9458                 if(!prepared)
9459                 {
9460                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9461                         prepared = true;
9462                         if(rsurface.batchnumvertices == 0)
9463                                 break;
9464                 }
9465                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9466                 {
9467                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9468                         d += fabs(PlaneDiff(vert, &p->plane));
9469                 }
9470                 if (bestd > d || bestplaneindex < 0)
9471                 {
9472                         bestd = d;
9473                         bestplaneindex = planeindex;
9474                 }
9475         }
9476         return bestplaneindex;
9477         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9478         // this situation though, as it might be better to render single larger
9479         // batches with useless stuff (backface culled for example) than to
9480         // render multiple smaller batches
9481 }
9482
9483 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9484 {
9485         int i;
9486         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9487         rsurface.passcolor4f_vertexbuffer = 0;
9488         rsurface.passcolor4f_bufferoffset = 0;
9489         for (i = 0;i < rsurface.batchnumvertices;i++)
9490                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9491 }
9492
9493 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9494 {
9495         int i;
9496         float f;
9497         const float *v;
9498         const float *c;
9499         float *c2;
9500         if (rsurface.passcolor4f)
9501         {
9502                 // generate color arrays
9503                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9504                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9505                 rsurface.passcolor4f_vertexbuffer = 0;
9506                 rsurface.passcolor4f_bufferoffset = 0;
9507                 for (i = 0, 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)
9508                 {
9509                         f = RSurf_FogVertex(v);
9510                         c2[0] = c[0] * f;
9511                         c2[1] = c[1] * f;
9512                         c2[2] = c[2] * f;
9513                         c2[3] = c[3];
9514                 }
9515         }
9516         else
9517         {
9518                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9519                 rsurface.passcolor4f_vertexbuffer = 0;
9520                 rsurface.passcolor4f_bufferoffset = 0;
9521                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9522                 {
9523                         f = RSurf_FogVertex(v);
9524                         c2[0] = f;
9525                         c2[1] = f;
9526                         c2[2] = f;
9527                         c2[3] = 1;
9528                 }
9529         }
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9533 {
9534         int i;
9535         float f;
9536         const float *v;
9537         const float *c;
9538         float *c2;
9539         if (!rsurface.passcolor4f)
9540                 return;
9541         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9542         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9543         rsurface.passcolor4f_vertexbuffer = 0;
9544         rsurface.passcolor4f_bufferoffset = 0;
9545         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)
9546         {
9547                 f = RSurf_FogVertex(v);
9548                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9549                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9550                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9551                 c2[3] = c[3];
9552         }
9553 }
9554
9555 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9556 {
9557         int i;
9558         const float *c;
9559         float *c2;
9560         if (!rsurface.passcolor4f)
9561                 return;
9562         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9563         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9567         {
9568                 c2[0] = c[0] * r;
9569                 c2[1] = c[1] * g;
9570                 c2[2] = c[2] * b;
9571                 c2[3] = c[3] * a;
9572         }
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9576 {
9577         int i;
9578         const float *c;
9579         float *c2;
9580         if (!rsurface.passcolor4f)
9581                 return;
9582         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9583         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9584         rsurface.passcolor4f_vertexbuffer = 0;
9585         rsurface.passcolor4f_bufferoffset = 0;
9586         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9587         {
9588                 c2[0] = c[0] + r_refdef.scene.ambient;
9589                 c2[1] = c[1] + r_refdef.scene.ambient;
9590                 c2[2] = c[2] + r_refdef.scene.ambient;
9591                 c2[3] = c[3];
9592         }
9593 }
9594
9595 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9596 {
9597         // TODO: optimize
9598         rsurface.passcolor4f = NULL;
9599         rsurface.passcolor4f_vertexbuffer = 0;
9600         rsurface.passcolor4f_bufferoffset = 0;
9601         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9602         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9603         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9604         GL_Color(r, g, b, a);
9605         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9606         RSurf_DrawBatch();
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9610 {
9611         // TODO: optimize applyfog && applycolor case
9612         // just apply fog if necessary, and tint the fog color array if necessary
9613         rsurface.passcolor4f = NULL;
9614         rsurface.passcolor4f_vertexbuffer = 0;
9615         rsurface.passcolor4f_bufferoffset = 0;
9616         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9617         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9618         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9619         GL_Color(r, g, b, a);
9620         RSurf_DrawBatch();
9621 }
9622
9623 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9624 {
9625         // TODO: optimize
9626         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9627         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9628         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9629         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9630         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9631         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9632         GL_Color(r, g, b, a);
9633         RSurf_DrawBatch();
9634 }
9635
9636 static void RSurf_DrawBatch_GL11_ClampColor(void)
9637 {
9638         int i;
9639         const float *c1;
9640         float *c2;
9641         if (!rsurface.passcolor4f)
9642                 return;
9643         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9644         {
9645                 c2[0] = bound(0.0f, c1[0], 1.0f);
9646                 c2[1] = bound(0.0f, c1[1], 1.0f);
9647                 c2[2] = bound(0.0f, c1[2], 1.0f);
9648                 c2[3] = bound(0.0f, c1[3], 1.0f);
9649         }
9650 }
9651
9652 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9653 {
9654         int i;
9655         float f;
9656         const float *v;
9657         const float *n;
9658         float *c;
9659         //vec3_t eyedir;
9660
9661         // fake shading
9662         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9663         rsurface.passcolor4f_vertexbuffer = 0;
9664         rsurface.passcolor4f_bufferoffset = 0;
9665         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)
9666         {
9667                 f = -DotProduct(r_refdef.view.forward, n);
9668                 f = max(0, f);
9669                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9670                 f *= r_refdef.lightmapintensity;
9671                 Vector4Set(c, f, f, f, 1);
9672         }
9673 }
9674
9675 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9676 {
9677         RSurf_DrawBatch_GL11_ApplyFakeLight();
9678         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9679         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9680         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9681         GL_Color(r, g, b, a);
9682         RSurf_DrawBatch();
9683 }
9684
9685 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9686 {
9687         int i;
9688         float f;
9689         float alpha;
9690         const float *v;
9691         const float *n;
9692         float *c;
9693         vec3_t ambientcolor;
9694         vec3_t diffusecolor;
9695         vec3_t lightdir;
9696         // TODO: optimize
9697         // model lighting
9698         VectorCopy(rsurface.modellight_lightdir, lightdir);
9699         f = 0.5f * r_refdef.lightmapintensity;
9700         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9701         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9702         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9703         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9704         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9705         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9706         alpha = *a;
9707         if (VectorLength2(diffusecolor) > 0)
9708         {
9709                 // q3-style directional shading
9710                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9711                 rsurface.passcolor4f_vertexbuffer = 0;
9712                 rsurface.passcolor4f_bufferoffset = 0;
9713                 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)
9714                 {
9715                         if ((f = DotProduct(n, lightdir)) > 0)
9716                                 VectorMA(ambientcolor, f, diffusecolor, c);
9717                         else
9718                                 VectorCopy(ambientcolor, c);
9719                         c[3] = alpha;
9720                 }
9721                 *r = 1;
9722                 *g = 1;
9723                 *b = 1;
9724                 *a = 1;
9725                 *applycolor = false;
9726         }
9727         else
9728         {
9729                 *r = ambientcolor[0];
9730                 *g = ambientcolor[1];
9731                 *b = ambientcolor[2];
9732                 rsurface.passcolor4f = NULL;
9733                 rsurface.passcolor4f_vertexbuffer = 0;
9734                 rsurface.passcolor4f_bufferoffset = 0;
9735         }
9736 }
9737
9738 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9739 {
9740         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9741         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9742         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9743         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9744         GL_Color(r, g, b, a);
9745         RSurf_DrawBatch();
9746 }
9747
9748 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9749 {
9750         int i;
9751         float f;
9752         const float *v;
9753         float *c;
9754
9755         // fake shading
9756         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9757         rsurface.passcolor4f_vertexbuffer = 0;
9758         rsurface.passcolor4f_bufferoffset = 0;
9759
9760         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9761         {
9762                 f = 1 - RSurf_FogVertex(v);
9763                 c[0] = r;
9764                 c[1] = g;
9765                 c[2] = b;
9766                 c[3] = f * a;
9767         }
9768 }
9769
9770 void RSurf_SetupDepthAndCulling(void)
9771 {
9772         // submodels are biased to avoid z-fighting with world surfaces that they
9773         // may be exactly overlapping (avoids z-fighting artifacts on certain
9774         // doors and things in Quake maps)
9775         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9776         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9777         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9778         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9779 }
9780
9781 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9782 {
9783         // transparent sky would be ridiculous
9784         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9785                 return;
9786         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9787         skyrenderlater = true;
9788         RSurf_SetupDepthAndCulling();
9789         GL_DepthMask(true);
9790         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9791         // skymasking on them, and Quake3 never did sky masking (unlike
9792         // software Quake and software Quake2), so disable the sky masking
9793         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9794         // and skymasking also looks very bad when noclipping outside the
9795         // level, so don't use it then either.
9796         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9797         {
9798                 R_Mesh_ResetTextureState();
9799                 if (skyrendermasked)
9800                 {
9801                         R_SetupShader_DepthOrShadow(false);
9802                         // depth-only (masking)
9803                         GL_ColorMask(0,0,0,0);
9804                         // just to make sure that braindead drivers don't draw
9805                         // anything despite that colormask...
9806                         GL_BlendFunc(GL_ZERO, GL_ONE);
9807                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808                         if (rsurface.batchvertex3fbuffer)
9809                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9810                         else
9811                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9812                 }
9813                 else
9814                 {
9815                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9816                         // fog sky
9817                         GL_BlendFunc(GL_ONE, GL_ZERO);
9818                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9819                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9820                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9821                 }
9822                 RSurf_DrawBatch();
9823                 if (skyrendermasked)
9824                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9825         }
9826         R_Mesh_ResetTextureState();
9827         GL_Color(1, 1, 1, 1);
9828 }
9829
9830 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9831 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9832 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9833 {
9834         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9835                 return;
9836         if (prepass)
9837         {
9838                 // render screenspace normalmap to texture
9839                 GL_DepthMask(true);
9840                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9841                 RSurf_DrawBatch();
9842         }
9843
9844         // bind lightmap texture
9845
9846         // water/refraction/reflection/camera surfaces have to be handled specially
9847         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9848         {
9849                 int start, end, startplaneindex;
9850                 for (start = 0;start < texturenumsurfaces;start = end)
9851                 {
9852                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9853                         if(startplaneindex < 0)
9854                         {
9855                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9856                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9857                                 end = start + 1;
9858                                 continue;
9859                         }
9860                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9861                                 ;
9862                         // now that we have a batch using the same planeindex, render it
9863                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9864                         {
9865                                 // render water or distortion background
9866                                 GL_DepthMask(true);
9867                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9868                                 RSurf_DrawBatch();
9869                                 // blend surface on top
9870                                 GL_DepthMask(false);
9871                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9872                                 RSurf_DrawBatch();
9873                         }
9874                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9875                         {
9876                                 // render surface with reflection texture as input
9877                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9878                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9879                                 RSurf_DrawBatch();
9880                         }
9881                 }
9882                 return;
9883         }
9884
9885         // render surface batch normally
9886         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9887         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);
9888         RSurf_DrawBatch();
9889 }
9890
9891 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9892 {
9893         // OpenGL 1.3 path - anything not completely ancient
9894         qboolean applycolor;
9895         qboolean applyfog;
9896         int layerindex;
9897         const texturelayer_t *layer;
9898         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);
9899         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9900
9901         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9902         {
9903                 vec4_t layercolor;
9904                 int layertexrgbscale;
9905                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9906                 {
9907                         if (layerindex == 0)
9908                                 GL_AlphaTest(true);
9909                         else
9910                         {
9911                                 GL_AlphaTest(false);
9912                                 GL_DepthFunc(GL_EQUAL);
9913                         }
9914                 }
9915                 GL_DepthMask(layer->depthmask && writedepth);
9916                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9917                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9918                 {
9919                         layertexrgbscale = 4;
9920                         VectorScale(layer->color, 0.25f, layercolor);
9921                 }
9922                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9923                 {
9924                         layertexrgbscale = 2;
9925                         VectorScale(layer->color, 0.5f, layercolor);
9926                 }
9927                 else
9928                 {
9929                         layertexrgbscale = 1;
9930                         VectorScale(layer->color, 1.0f, layercolor);
9931                 }
9932                 layercolor[3] = layer->color[3];
9933                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9934                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9935                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9936                 switch (layer->type)
9937                 {
9938                 case TEXTURELAYERTYPE_LITTEXTURE:
9939                         // single-pass lightmapped texture with 2x rgbscale
9940                         R_Mesh_TexBind(0, r_texture_white);
9941                         R_Mesh_TexMatrix(0, NULL);
9942                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9943                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9944                         R_Mesh_TexBind(1, layer->texture);
9945                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9946                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9947                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9948                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9949                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9950                         else if (FAKELIGHT_ENABLED)
9951                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9952                         else if (rsurface.uselightmaptexture)
9953                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9954                         else
9955                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9956                         break;
9957                 case TEXTURELAYERTYPE_TEXTURE:
9958                         // singletexture unlit texture with transparency support
9959                         R_Mesh_TexBind(0, layer->texture);
9960                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9961                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9962                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9963                         R_Mesh_TexBind(1, 0);
9964                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9965                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9966                         break;
9967                 case TEXTURELAYERTYPE_FOG:
9968                         // singletexture fogging
9969                         if (layer->texture)
9970                         {
9971                                 R_Mesh_TexBind(0, layer->texture);
9972                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9973                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9974                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9975                         }
9976                         else
9977                         {
9978                                 R_Mesh_TexBind(0, 0);
9979                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9980                         }
9981                         R_Mesh_TexBind(1, 0);
9982                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9983                         // generate a color array for the fog pass
9984                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9985                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9986                         RSurf_DrawBatch();
9987                         break;
9988                 default:
9989                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9990                 }
9991         }
9992         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9993         {
9994                 GL_DepthFunc(GL_LEQUAL);
9995                 GL_AlphaTest(false);
9996         }
9997 }
9998
9999 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10000 {
10001         // OpenGL 1.1 - crusty old voodoo path
10002         qboolean applyfog;
10003         int layerindex;
10004         const texturelayer_t *layer;
10005         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);
10006         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10007
10008         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10009         {
10010                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10011                 {
10012                         if (layerindex == 0)
10013                                 GL_AlphaTest(true);
10014                         else
10015                         {
10016                                 GL_AlphaTest(false);
10017                                 GL_DepthFunc(GL_EQUAL);
10018                         }
10019                 }
10020                 GL_DepthMask(layer->depthmask && writedepth);
10021                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10022                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10023                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10024                 switch (layer->type)
10025                 {
10026                 case TEXTURELAYERTYPE_LITTEXTURE:
10027                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10028                         {
10029                                 // two-pass lit texture with 2x rgbscale
10030                                 // first the lightmap pass
10031                                 R_Mesh_TexBind(0, r_texture_white);
10032                                 R_Mesh_TexMatrix(0, NULL);
10033                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10034                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10035                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10036                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10037                                 else if (FAKELIGHT_ENABLED)
10038                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10039                                 else if (rsurface.uselightmaptexture)
10040                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10041                                 else
10042                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10043                                 // then apply the texture to it
10044                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10045                                 R_Mesh_TexBind(0, layer->texture);
10046                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10047                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10048                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10049                                 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);
10050                         }
10051                         else
10052                         {
10053                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10054                                 R_Mesh_TexBind(0, layer->texture);
10055                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10056                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10057                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10058                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10059                                         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);
10060                                 else
10061                                         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);
10062                         }
10063                         break;
10064                 case TEXTURELAYERTYPE_TEXTURE:
10065                         // singletexture unlit texture with transparency support
10066                         R_Mesh_TexBind(0, layer->texture);
10067                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10068                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10069                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10070                         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);
10071                         break;
10072                 case TEXTURELAYERTYPE_FOG:
10073                         // singletexture fogging
10074                         if (layer->texture)
10075                         {
10076                                 R_Mesh_TexBind(0, layer->texture);
10077                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10078                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10079                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10080                         }
10081                         else
10082                         {
10083                                 R_Mesh_TexBind(0, 0);
10084                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10085                         }
10086                         // generate a color array for the fog pass
10087                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10088                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10089                         RSurf_DrawBatch();
10090                         break;
10091                 default:
10092                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10093                 }
10094         }
10095         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10096         {
10097                 GL_DepthFunc(GL_LEQUAL);
10098                 GL_AlphaTest(false);
10099         }
10100 }
10101
10102 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10103 {
10104         int vi;
10105         int j;
10106         r_vertexgeneric_t *batchvertex;
10107         float c[4];
10108
10109 //      R_Mesh_ResetTextureState();
10110         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10111
10112         if(rsurface.texture && rsurface.texture->currentskinframe)
10113         {
10114                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10115                 c[3] *= rsurface.texture->currentalpha;
10116         }
10117         else
10118         {
10119                 c[0] = 1;
10120                 c[1] = 0;
10121                 c[2] = 1;
10122                 c[3] = 1;
10123         }
10124
10125         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10126         {
10127                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10128                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10129                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10130         }
10131
10132         // brighten it up (as texture value 127 means "unlit")
10133         c[0] *= 2 * r_refdef.view.colorscale;
10134         c[1] *= 2 * r_refdef.view.colorscale;
10135         c[2] *= 2 * r_refdef.view.colorscale;
10136
10137         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10138                 c[3] *= r_wateralpha.value;
10139
10140         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10141         {
10142                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10143                 GL_DepthMask(false);
10144         }
10145         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10146         {
10147                 GL_BlendFunc(GL_ONE, GL_ONE);
10148                 GL_DepthMask(false);
10149         }
10150         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10151         {
10152                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10153                 GL_DepthMask(false);
10154         }
10155         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10156         {
10157                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10158                 GL_DepthMask(false);
10159         }
10160         else
10161         {
10162                 GL_BlendFunc(GL_ONE, GL_ZERO);
10163                 GL_DepthMask(writedepth);
10164         }
10165
10166         if (r_showsurfaces.integer == 3)
10167         {
10168                 rsurface.passcolor4f = NULL;
10169
10170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10171                 {
10172                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10173
10174                         rsurface.passcolor4f = NULL;
10175                         rsurface.passcolor4f_vertexbuffer = 0;
10176                         rsurface.passcolor4f_bufferoffset = 0;
10177                 }
10178                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10179                 {
10180                         qboolean applycolor = true;
10181                         float one = 1.0;
10182
10183                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10184
10185                         r_refdef.lightmapintensity = 1;
10186                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10187                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10188                 }
10189                 else if (FAKELIGHT_ENABLED)
10190                 {
10191                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10192
10193                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10194                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10195                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10196                 }
10197                 else
10198                 {
10199                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200
10201                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10202                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10203                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10204                 }
10205
10206                 if(!rsurface.passcolor4f)
10207                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10208
10209                 RSurf_DrawBatch_GL11_ApplyAmbient();
10210                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10211                 if(r_refdef.fogenabled)
10212                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10213                 RSurf_DrawBatch_GL11_ClampColor();
10214
10215                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10216                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10217                 RSurf_DrawBatch();
10218         }
10219         else if (!r_refdef.view.showdebug)
10220         {
10221                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10222                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10223                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10224                 {
10225                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10226                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10227                 }
10228                 R_Mesh_PrepareVertices_Generic_Unlock();
10229                 RSurf_DrawBatch();
10230         }
10231         else if (r_showsurfaces.integer == 4)
10232         {
10233                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10234                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10235                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10236                 {
10237                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10238                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10239                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10240                 }
10241                 R_Mesh_PrepareVertices_Generic_Unlock();
10242                 RSurf_DrawBatch();
10243         }
10244         else if (r_showsurfaces.integer == 2)
10245         {
10246                 const int *e;
10247                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10248                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10249                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10250                 {
10251                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10252                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10253                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10254                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10255                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10256                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10257                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10258                 }
10259                 R_Mesh_PrepareVertices_Generic_Unlock();
10260                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10261         }
10262         else
10263         {
10264                 int texturesurfaceindex;
10265                 int k;
10266                 const msurface_t *surface;
10267                 float surfacecolor4f[4];
10268                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10269                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10270                 vi = 0;
10271                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10272                 {
10273                         surface = texturesurfacelist[texturesurfaceindex];
10274                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10275                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10276                         for (j = 0;j < surface->num_vertices;j++)
10277                         {
10278                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10279                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10280                                 vi++;
10281                         }
10282                 }
10283                 R_Mesh_PrepareVertices_Generic_Unlock();
10284                 RSurf_DrawBatch();
10285         }
10286 }
10287
10288 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10289 {
10290         CHECKGLERROR
10291         RSurf_SetupDepthAndCulling();
10292         if (r_showsurfaces.integer)
10293         {
10294                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10295                 return;
10296         }
10297         switch (vid.renderpath)
10298         {
10299         case RENDERPATH_GL20:
10300         case RENDERPATH_D3D9:
10301         case RENDERPATH_D3D10:
10302         case RENDERPATH_D3D11:
10303         case RENDERPATH_SOFT:
10304         case RENDERPATH_GLES2:
10305                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10306                 break;
10307         case RENDERPATH_GL13:
10308         case RENDERPATH_GLES1:
10309                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10310                 break;
10311         case RENDERPATH_GL11:
10312                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10313                 break;
10314         }
10315         CHECKGLERROR
10316 }
10317
10318 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10319 {
10320         CHECKGLERROR
10321         RSurf_SetupDepthAndCulling();
10322         if (r_showsurfaces.integer)
10323         {
10324                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10325                 return;
10326         }
10327         switch (vid.renderpath)
10328         {
10329         case RENDERPATH_GL20:
10330         case RENDERPATH_D3D9:
10331         case RENDERPATH_D3D10:
10332         case RENDERPATH_D3D11:
10333         case RENDERPATH_SOFT:
10334         case RENDERPATH_GLES2:
10335                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10336                 break;
10337         case RENDERPATH_GL13:
10338         case RENDERPATH_GLES1:
10339                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10340                 break;
10341         case RENDERPATH_GL11:
10342                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10343                 break;
10344         }
10345         CHECKGLERROR
10346 }
10347
10348 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10349 {
10350         int i, j;
10351         int texturenumsurfaces, endsurface;
10352         texture_t *texture;
10353         const msurface_t *surface;
10354         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10355
10356         // if the model is static it doesn't matter what value we give for
10357         // wantnormals and wanttangents, so this logic uses only rules applicable
10358         // to a model, knowing that they are meaningless otherwise
10359         if (ent == r_refdef.scene.worldentity)
10360                 RSurf_ActiveWorldEntity();
10361         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10362                 RSurf_ActiveModelEntity(ent, false, false, false);
10363         else
10364         {
10365                 switch (vid.renderpath)
10366                 {
10367                 case RENDERPATH_GL20:
10368                 case RENDERPATH_D3D9:
10369                 case RENDERPATH_D3D10:
10370                 case RENDERPATH_D3D11:
10371                 case RENDERPATH_SOFT:
10372                 case RENDERPATH_GLES2:
10373                         RSurf_ActiveModelEntity(ent, true, true, false);
10374                         break;
10375                 case RENDERPATH_GL11:
10376                 case RENDERPATH_GL13:
10377                 case RENDERPATH_GLES1:
10378                         RSurf_ActiveModelEntity(ent, true, false, false);
10379                         break;
10380                 }
10381         }
10382
10383         if (r_transparentdepthmasking.integer)
10384         {
10385                 qboolean setup = false;
10386                 for (i = 0;i < numsurfaces;i = j)
10387                 {
10388                         j = i + 1;
10389                         surface = rsurface.modelsurfaces + surfacelist[i];
10390                         texture = surface->texture;
10391                         rsurface.texture = R_GetCurrentTexture(texture);
10392                         rsurface.lightmaptexture = NULL;
10393                         rsurface.deluxemaptexture = NULL;
10394                         rsurface.uselightmaptexture = false;
10395                         // scan ahead until we find a different texture
10396                         endsurface = min(i + 1024, numsurfaces);
10397                         texturenumsurfaces = 0;
10398                         texturesurfacelist[texturenumsurfaces++] = surface;
10399                         for (;j < endsurface;j++)
10400                         {
10401                                 surface = rsurface.modelsurfaces + surfacelist[j];
10402                                 if (texture != surface->texture)
10403                                         break;
10404                                 texturesurfacelist[texturenumsurfaces++] = surface;
10405                         }
10406                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10407                                 continue;
10408                         // render the range of surfaces as depth
10409                         if (!setup)
10410                         {
10411                                 setup = true;
10412                                 GL_ColorMask(0,0,0,0);
10413                                 GL_Color(1,1,1,1);
10414                                 GL_DepthTest(true);
10415                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10416                                 GL_DepthMask(true);
10417 //                              R_Mesh_ResetTextureState();
10418                                 R_SetupShader_DepthOrShadow(false);
10419                         }
10420                         RSurf_SetupDepthAndCulling();
10421                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10422                         if (rsurface.batchvertex3fbuffer)
10423                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10424                         else
10425                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10426                         RSurf_DrawBatch();
10427                 }
10428                 if (setup)
10429                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10430         }
10431
10432         for (i = 0;i < numsurfaces;i = j)
10433         {
10434                 j = i + 1;
10435                 surface = rsurface.modelsurfaces + surfacelist[i];
10436                 texture = surface->texture;
10437                 rsurface.texture = R_GetCurrentTexture(texture);
10438                 // scan ahead until we find a different texture
10439                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10440                 texturenumsurfaces = 0;
10441                 texturesurfacelist[texturenumsurfaces++] = surface;
10442                 if(FAKELIGHT_ENABLED)
10443                 {
10444                         rsurface.lightmaptexture = NULL;
10445                         rsurface.deluxemaptexture = NULL;
10446                         rsurface.uselightmaptexture = false;
10447                         for (;j < endsurface;j++)
10448                         {
10449                                 surface = rsurface.modelsurfaces + surfacelist[j];
10450                                 if (texture != surface->texture)
10451                                         break;
10452                                 texturesurfacelist[texturenumsurfaces++] = surface;
10453                         }
10454                 }
10455                 else
10456                 {
10457                         rsurface.lightmaptexture = surface->lightmaptexture;
10458                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10459                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10460                         for (;j < endsurface;j++)
10461                         {
10462                                 surface = rsurface.modelsurfaces + surfacelist[j];
10463                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10464                                         break;
10465                                 texturesurfacelist[texturenumsurfaces++] = surface;
10466                         }
10467                 }
10468                 // render the range of surfaces
10469                 if (ent == r_refdef.scene.worldentity)
10470                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10471                 else
10472                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10473         }
10474         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10475 }
10476
10477 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10478 {
10479         // transparent surfaces get pushed off into the transparent queue
10480         int surfacelistindex;
10481         const msurface_t *surface;
10482         vec3_t tempcenter, center;
10483         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10484         {
10485                 surface = texturesurfacelist[surfacelistindex];
10486                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10487                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10488                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10489                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10490                 if (queueentity->transparent_offset) // transparent offset
10491                 {
10492                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10493                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10494                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10495                 }
10496                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10497         }
10498 }
10499
10500 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10501 {
10502         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10503                 return;
10504         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10505                 return;
10506         RSurf_SetupDepthAndCulling();
10507         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10508         if (rsurface.batchvertex3fbuffer)
10509                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10510         else
10511                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10512         RSurf_DrawBatch();
10513 }
10514
10515 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10516 {
10517         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10518         CHECKGLERROR
10519         if (depthonly)
10520                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10521         else if (prepass)
10522         {
10523                 if (!rsurface.texture->currentnumlayers)
10524                         return;
10525                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10526                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10527                 else
10528                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10529         }
10530         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10531                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10532         else if (!rsurface.texture->currentnumlayers)
10533                 return;
10534         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10535         {
10536                 // in the deferred case, transparent surfaces were queued during prepass
10537                 if (!r_shadow_usingdeferredprepass)
10538                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10539         }
10540         else
10541         {
10542                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10543                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10544         }
10545         CHECKGLERROR
10546 }
10547
10548 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10549 {
10550         int i, j;
10551         texture_t *texture;
10552         R_FrameData_SetMark();
10553         // break the surface list down into batches by texture and use of lightmapping
10554         for (i = 0;i < numsurfaces;i = j)
10555         {
10556                 j = i + 1;
10557                 // texture is the base texture pointer, rsurface.texture is the
10558                 // current frame/skin the texture is directing us to use (for example
10559                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10560                 // use skin 1 instead)
10561                 texture = surfacelist[i]->texture;
10562                 rsurface.texture = R_GetCurrentTexture(texture);
10563                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10564                 {
10565                         // if this texture is not the kind we want, skip ahead to the next one
10566                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10567                                 ;
10568                         continue;
10569                 }
10570                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10571                 {
10572                         rsurface.lightmaptexture = NULL;
10573                         rsurface.deluxemaptexture = NULL;
10574                         rsurface.uselightmaptexture = false;
10575                         // simply scan ahead until we find a different texture or lightmap state
10576                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10577                                 ;
10578                 }
10579                 else
10580                 {
10581                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10582                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10583                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10584                         // simply scan ahead until we find a different texture or lightmap state
10585                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10586                                 ;
10587                 }
10588                 // render the range of surfaces
10589                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10590         }
10591         R_FrameData_ReturnToMark();
10592 }
10593
10594 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10595 {
10596         CHECKGLERROR
10597         if (depthonly)
10598                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10599         else if (prepass)
10600         {
10601                 if (!rsurface.texture->currentnumlayers)
10602                         return;
10603                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10604                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10605                 else
10606                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10607         }
10608         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10609                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10610         else if (!rsurface.texture->currentnumlayers)
10611                 return;
10612         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10613         {
10614                 // in the deferred case, transparent surfaces were queued during prepass
10615                 if (!r_shadow_usingdeferredprepass)
10616                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10617         }
10618         else
10619         {
10620                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10621                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10622         }
10623         CHECKGLERROR
10624 }
10625
10626 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10627 {
10628         int i, j;
10629         texture_t *texture;
10630         R_FrameData_SetMark();
10631         // break the surface list down into batches by texture and use of lightmapping
10632         for (i = 0;i < numsurfaces;i = j)
10633         {
10634                 j = i + 1;
10635                 // texture is the base texture pointer, rsurface.texture is the
10636                 // current frame/skin the texture is directing us to use (for example
10637                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10638                 // use skin 1 instead)
10639                 texture = surfacelist[i]->texture;
10640                 rsurface.texture = R_GetCurrentTexture(texture);
10641                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10642                 {
10643                         // if this texture is not the kind we want, skip ahead to the next one
10644                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10645                                 ;
10646                         continue;
10647                 }
10648                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10649                 {
10650                         rsurface.lightmaptexture = NULL;
10651                         rsurface.deluxemaptexture = NULL;
10652                         rsurface.uselightmaptexture = false;
10653                         // simply scan ahead until we find a different texture or lightmap state
10654                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10655                                 ;
10656                 }
10657                 else
10658                 {
10659                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10660                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10661                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10662                         // simply scan ahead until we find a different texture or lightmap state
10663                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10664                                 ;
10665                 }
10666                 // render the range of surfaces
10667                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10668         }
10669         R_FrameData_ReturnToMark();
10670 }
10671
10672 float locboxvertex3f[6*4*3] =
10673 {
10674         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10675         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10676         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10677         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10678         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10679         1,0,0, 0,0,0, 0,1,0, 1,1,0
10680 };
10681
10682 unsigned short locboxelements[6*2*3] =
10683 {
10684          0, 1, 2, 0, 2, 3,
10685          4, 5, 6, 4, 6, 7,
10686          8, 9,10, 8,10,11,
10687         12,13,14, 12,14,15,
10688         16,17,18, 16,18,19,
10689         20,21,22, 20,22,23
10690 };
10691
10692 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10693 {
10694         int i, j;
10695         cl_locnode_t *loc = (cl_locnode_t *)ent;
10696         vec3_t mins, size;
10697         float vertex3f[6*4*3];
10698         CHECKGLERROR
10699         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10700         GL_DepthMask(false);
10701         GL_DepthRange(0, 1);
10702         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10703         GL_DepthTest(true);
10704         GL_CullFace(GL_NONE);
10705         R_EntityMatrix(&identitymatrix);
10706
10707 //      R_Mesh_ResetTextureState();
10708
10709         i = surfacelist[0];
10710         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10711                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10712                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10713                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10714
10715         if (VectorCompare(loc->mins, loc->maxs))
10716         {
10717                 VectorSet(size, 2, 2, 2);
10718                 VectorMA(loc->mins, -0.5f, size, mins);
10719         }
10720         else
10721         {
10722                 VectorCopy(loc->mins, mins);
10723                 VectorSubtract(loc->maxs, loc->mins, size);
10724         }
10725
10726         for (i = 0;i < 6*4*3;)
10727                 for (j = 0;j < 3;j++, i++)
10728                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10729
10730         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10731         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10732         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10733 }
10734
10735 void R_DrawLocs(void)
10736 {
10737         int index;
10738         cl_locnode_t *loc, *nearestloc;
10739         vec3_t center;
10740         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10741         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10742         {
10743                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10744                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10745         }
10746 }
10747
10748 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10749 {
10750         if (decalsystem->decals)
10751                 Mem_Free(decalsystem->decals);
10752         memset(decalsystem, 0, sizeof(*decalsystem));
10753 }
10754
10755 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)
10756 {
10757         tridecal_t *decal;
10758         tridecal_t *decals;
10759         int i;
10760
10761         // expand or initialize the system
10762         if (decalsystem->maxdecals <= decalsystem->numdecals)
10763         {
10764                 decalsystem_t old = *decalsystem;
10765                 qboolean useshortelements;
10766                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10767                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10768                 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)));
10769                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10770                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10771                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10772                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10773                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10774                 if (decalsystem->numdecals)
10775                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10776                 if (old.decals)
10777                         Mem_Free(old.decals);
10778                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10779                         decalsystem->element3i[i] = i;
10780                 if (useshortelements)
10781                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10782                                 decalsystem->element3s[i] = i;
10783         }
10784
10785         // grab a decal and search for another free slot for the next one
10786         decals = decalsystem->decals;
10787         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10788         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10789                 ;
10790         decalsystem->freedecal = i;
10791         if (decalsystem->numdecals <= i)
10792                 decalsystem->numdecals = i + 1;
10793
10794         // initialize the decal
10795         decal->lived = 0;
10796         decal->triangleindex = triangleindex;
10797         decal->surfaceindex = surfaceindex;
10798         decal->decalsequence = decalsequence;
10799         decal->color4f[0][0] = c0[0];
10800         decal->color4f[0][1] = c0[1];
10801         decal->color4f[0][2] = c0[2];
10802         decal->color4f[0][3] = 1;
10803         decal->color4f[1][0] = c1[0];
10804         decal->color4f[1][1] = c1[1];
10805         decal->color4f[1][2] = c1[2];
10806         decal->color4f[1][3] = 1;
10807         decal->color4f[2][0] = c2[0];
10808         decal->color4f[2][1] = c2[1];
10809         decal->color4f[2][2] = c2[2];
10810         decal->color4f[2][3] = 1;
10811         decal->vertex3f[0][0] = v0[0];
10812         decal->vertex3f[0][1] = v0[1];
10813         decal->vertex3f[0][2] = v0[2];
10814         decal->vertex3f[1][0] = v1[0];
10815         decal->vertex3f[1][1] = v1[1];
10816         decal->vertex3f[1][2] = v1[2];
10817         decal->vertex3f[2][0] = v2[0];
10818         decal->vertex3f[2][1] = v2[1];
10819         decal->vertex3f[2][2] = v2[2];
10820         decal->texcoord2f[0][0] = t0[0];
10821         decal->texcoord2f[0][1] = t0[1];
10822         decal->texcoord2f[1][0] = t1[0];
10823         decal->texcoord2f[1][1] = t1[1];
10824         decal->texcoord2f[2][0] = t2[0];
10825         decal->texcoord2f[2][1] = t2[1];
10826         TriangleNormal(v0, v1, v2, decal->plane);
10827         VectorNormalize(decal->plane);
10828         decal->plane[3] = DotProduct(v0, decal->plane);
10829 }
10830
10831 extern cvar_t cl_decals_bias;
10832 extern cvar_t cl_decals_models;
10833 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10834 // baseparms, parms, temps
10835 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)
10836 {
10837         int cornerindex;
10838         int index;
10839         float v[9][3];
10840         const float *vertex3f;
10841         const float *normal3f;
10842         int numpoints;
10843         float points[2][9][3];
10844         float temp[3];
10845         float tc[9][2];
10846         float f;
10847         float c[9][4];
10848         const int *e;
10849
10850         e = rsurface.modelelement3i + 3*triangleindex;
10851
10852         vertex3f = rsurface.modelvertex3f;
10853         normal3f = rsurface.modelnormal3f;
10854
10855         if (normal3f)
10856         {
10857                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10858                 {
10859                         index = 3*e[cornerindex];
10860                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10861                 }
10862         }
10863         else
10864         {
10865                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10866                 {
10867                         index = 3*e[cornerindex];
10868                         VectorCopy(vertex3f + index, v[cornerindex]);
10869                 }
10870         }
10871
10872         // cull backfaces
10873         //TriangleNormal(v[0], v[1], v[2], normal);
10874         //if (DotProduct(normal, localnormal) < 0.0f)
10875         //      continue;
10876         // clip by each of the box planes formed from the projection matrix
10877         // if anything survives, we emit the decal
10878         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]);
10879         if (numpoints < 3)
10880                 return;
10881         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]);
10882         if (numpoints < 3)
10883                 return;
10884         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]);
10885         if (numpoints < 3)
10886                 return;
10887         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]);
10888         if (numpoints < 3)
10889                 return;
10890         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]);
10891         if (numpoints < 3)
10892                 return;
10893         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]);
10894         if (numpoints < 3)
10895                 return;
10896         // some part of the triangle survived, so we have to accept it...
10897         if (dynamic)
10898         {
10899                 // dynamic always uses the original triangle
10900                 numpoints = 3;
10901                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10902                 {
10903                         index = 3*e[cornerindex];
10904                         VectorCopy(vertex3f + index, v[cornerindex]);
10905                 }
10906         }
10907         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10908         {
10909                 // convert vertex positions to texcoords
10910                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10911                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10912                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10913                 // calculate distance fade from the projection origin
10914                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10915                 f = bound(0.0f, f, 1.0f);
10916                 c[cornerindex][0] = r * f;
10917                 c[cornerindex][1] = g * f;
10918                 c[cornerindex][2] = b * f;
10919                 c[cornerindex][3] = 1.0f;
10920                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10921         }
10922         if (dynamic)
10923                 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);
10924         else
10925                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10926                         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);
10927 }
10928 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)
10929 {
10930         matrix4x4_t projection;
10931         decalsystem_t *decalsystem;
10932         qboolean dynamic;
10933         dp_model_t *model;
10934         const msurface_t *surface;
10935         const msurface_t *surfaces;
10936         const int *surfacelist;
10937         const texture_t *texture;
10938         int numtriangles;
10939         int numsurfacelist;
10940         int surfacelistindex;
10941         int surfaceindex;
10942         int triangleindex;
10943         float localorigin[3];
10944         float localnormal[3];
10945         float localmins[3];
10946         float localmaxs[3];
10947         float localsize;
10948         //float normal[3];
10949         float planes[6][4];
10950         float angles[3];
10951         bih_t *bih;
10952         int bih_triangles_count;
10953         int bih_triangles[256];
10954         int bih_surfaces[256];
10955
10956         decalsystem = &ent->decalsystem;
10957         model = ent->model;
10958         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10959         {
10960                 R_DecalSystem_Reset(&ent->decalsystem);
10961                 return;
10962         }
10963
10964         if (!model->brush.data_leafs && !cl_decals_models.integer)
10965         {
10966                 if (decalsystem->model)
10967                         R_DecalSystem_Reset(decalsystem);
10968                 return;
10969         }
10970
10971         if (decalsystem->model != model)
10972                 R_DecalSystem_Reset(decalsystem);
10973         decalsystem->model = model;
10974
10975         RSurf_ActiveModelEntity(ent, true, false, false);
10976
10977         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10978         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10979         VectorNormalize(localnormal);
10980         localsize = worldsize*rsurface.inversematrixscale;
10981         localmins[0] = localorigin[0] - localsize;
10982         localmins[1] = localorigin[1] - localsize;
10983         localmins[2] = localorigin[2] - localsize;
10984         localmaxs[0] = localorigin[0] + localsize;
10985         localmaxs[1] = localorigin[1] + localsize;
10986         localmaxs[2] = localorigin[2] + localsize;
10987
10988         //VectorCopy(localnormal, planes[4]);
10989         //VectorVectors(planes[4], planes[2], planes[0]);
10990         AnglesFromVectors(angles, localnormal, NULL, false);
10991         AngleVectors(angles, planes[0], planes[2], planes[4]);
10992         VectorNegate(planes[0], planes[1]);
10993         VectorNegate(planes[2], planes[3]);
10994         VectorNegate(planes[4], planes[5]);
10995         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10996         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10997         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10998         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10999         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11000         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11001
11002 #if 1
11003 // works
11004 {
11005         matrix4x4_t forwardprojection;
11006         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11007         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11008 }
11009 #else
11010 // broken
11011 {
11012         float projectionvector[4][3];
11013         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11014         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11015         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11016         projectionvector[0][0] = planes[0][0] * ilocalsize;
11017         projectionvector[0][1] = planes[1][0] * ilocalsize;
11018         projectionvector[0][2] = planes[2][0] * ilocalsize;
11019         projectionvector[1][0] = planes[0][1] * ilocalsize;
11020         projectionvector[1][1] = planes[1][1] * ilocalsize;
11021         projectionvector[1][2] = planes[2][1] * ilocalsize;
11022         projectionvector[2][0] = planes[0][2] * ilocalsize;
11023         projectionvector[2][1] = planes[1][2] * ilocalsize;
11024         projectionvector[2][2] = planes[2][2] * ilocalsize;
11025         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11026         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11027         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11028         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11029 }
11030 #endif
11031
11032         dynamic = model->surfmesh.isanimated;
11033         numsurfacelist = model->nummodelsurfaces;
11034         surfacelist = model->sortedmodelsurfaces;
11035         surfaces = model->data_surfaces;
11036
11037         bih = NULL;
11038         bih_triangles_count = -1;
11039         if(!dynamic)
11040         {
11041                 if(model->render_bih.numleafs)
11042                         bih = &model->render_bih;
11043                 else if(model->collision_bih.numleafs)
11044                         bih = &model->collision_bih;
11045         }
11046         if(bih)
11047                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11048         if(bih_triangles_count == 0)
11049                 return;
11050         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11051                 return;
11052         if(bih_triangles_count > 0)
11053         {
11054                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11055                 {
11056                         surfaceindex = bih_surfaces[triangleindex];
11057                         surface = surfaces + surfaceindex;
11058                         texture = surface->texture;
11059                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11060                                 continue;
11061                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11062                                 continue;
11063                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11064                 }
11065         }
11066         else
11067         {
11068                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11069                 {
11070                         surfaceindex = surfacelist[surfacelistindex];
11071                         surface = surfaces + surfaceindex;
11072                         // check cull box first because it rejects more than any other check
11073                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11074                                 continue;
11075                         // skip transparent surfaces
11076                         texture = surface->texture;
11077                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11078                                 continue;
11079                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11080                                 continue;
11081                         numtriangles = surface->num_triangles;
11082                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11083                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11084                 }
11085         }
11086 }
11087
11088 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11089 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)
11090 {
11091         int renderentityindex;
11092         float worldmins[3];
11093         float worldmaxs[3];
11094         entity_render_t *ent;
11095
11096         if (!cl_decals_newsystem.integer)
11097                 return;
11098
11099         worldmins[0] = worldorigin[0] - worldsize;
11100         worldmins[1] = worldorigin[1] - worldsize;
11101         worldmins[2] = worldorigin[2] - worldsize;
11102         worldmaxs[0] = worldorigin[0] + worldsize;
11103         worldmaxs[1] = worldorigin[1] + worldsize;
11104         worldmaxs[2] = worldorigin[2] + worldsize;
11105
11106         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11107
11108         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11109         {
11110                 ent = r_refdef.scene.entities[renderentityindex];
11111                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11112                         continue;
11113
11114                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11115         }
11116 }
11117
11118 typedef struct r_decalsystem_splatqueue_s
11119 {
11120         vec3_t worldorigin;
11121         vec3_t worldnormal;
11122         float color[4];
11123         float tcrange[4];
11124         float worldsize;
11125         int decalsequence;
11126 }
11127 r_decalsystem_splatqueue_t;
11128
11129 int r_decalsystem_numqueued = 0;
11130 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11131
11132 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)
11133 {
11134         r_decalsystem_splatqueue_t *queue;
11135
11136         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11137                 return;
11138
11139         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11140         VectorCopy(worldorigin, queue->worldorigin);
11141         VectorCopy(worldnormal, queue->worldnormal);
11142         Vector4Set(queue->color, r, g, b, a);
11143         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11144         queue->worldsize = worldsize;
11145         queue->decalsequence = cl.decalsequence++;
11146 }
11147
11148 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11149 {
11150         int i;
11151         r_decalsystem_splatqueue_t *queue;
11152
11153         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11154                 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);
11155         r_decalsystem_numqueued = 0;
11156 }
11157
11158 extern cvar_t cl_decals_max;
11159 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11160 {
11161         int i;
11162         decalsystem_t *decalsystem = &ent->decalsystem;
11163         int numdecals;
11164         int killsequence;
11165         tridecal_t *decal;
11166         float frametime;
11167         float lifetime;
11168
11169         if (!decalsystem->numdecals)
11170                 return;
11171
11172         if (r_showsurfaces.integer)
11173                 return;
11174
11175         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11176         {
11177                 R_DecalSystem_Reset(decalsystem);
11178                 return;
11179         }
11180
11181         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11182         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11183
11184         if (decalsystem->lastupdatetime)
11185                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11186         else
11187                 frametime = 0;
11188         decalsystem->lastupdatetime = r_refdef.scene.time;
11189         decal = decalsystem->decals;
11190         numdecals = decalsystem->numdecals;
11191
11192         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11193         {
11194                 if (decal->color4f[0][3])
11195                 {
11196                         decal->lived += frametime;
11197                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11198                         {
11199                                 memset(decal, 0, sizeof(*decal));
11200                                 if (decalsystem->freedecal > i)
11201                                         decalsystem->freedecal = i;
11202                         }
11203                 }
11204         }
11205         decal = decalsystem->decals;
11206         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11207                 numdecals--;
11208
11209         // collapse the array by shuffling the tail decals into the gaps
11210         for (;;)
11211         {
11212                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11213                         decalsystem->freedecal++;
11214                 if (decalsystem->freedecal == numdecals)
11215                         break;
11216                 decal[decalsystem->freedecal] = decal[--numdecals];
11217         }
11218
11219         decalsystem->numdecals = numdecals;
11220
11221         if (numdecals <= 0)
11222         {
11223                 // if there are no decals left, reset decalsystem
11224                 R_DecalSystem_Reset(decalsystem);
11225         }
11226 }
11227
11228 extern skinframe_t *decalskinframe;
11229 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11230 {
11231         int i;
11232         decalsystem_t *decalsystem = &ent->decalsystem;
11233         int numdecals;
11234         tridecal_t *decal;
11235         float faderate;
11236         float alpha;
11237         float *v3f;
11238         float *c4f;
11239         float *t2f;
11240         const int *e;
11241         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11242         int numtris = 0;
11243
11244         numdecals = decalsystem->numdecals;
11245         if (!numdecals)
11246                 return;
11247
11248         if (r_showsurfaces.integer)
11249                 return;
11250
11251         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11252         {
11253                 R_DecalSystem_Reset(decalsystem);
11254                 return;
11255         }
11256
11257         // if the model is static it doesn't matter what value we give for
11258         // wantnormals and wanttangents, so this logic uses only rules applicable
11259         // to a model, knowing that they are meaningless otherwise
11260         if (ent == r_refdef.scene.worldentity)
11261                 RSurf_ActiveWorldEntity();
11262         else
11263                 RSurf_ActiveModelEntity(ent, false, false, false);
11264
11265         decalsystem->lastupdatetime = r_refdef.scene.time;
11266         decal = decalsystem->decals;
11267
11268         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11269
11270         // update vertex positions for animated models
11271         v3f = decalsystem->vertex3f;
11272         c4f = decalsystem->color4f;
11273         t2f = decalsystem->texcoord2f;
11274         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11275         {
11276                 if (!decal->color4f[0][3])
11277                         continue;
11278
11279                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11280                         continue;
11281
11282                 // skip backfaces
11283                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11284                         continue;
11285
11286                 // update color values for fading decals
11287                 if (decal->lived >= cl_decals_time.value)
11288                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11289                 else
11290                         alpha = 1.0f;
11291
11292                 c4f[ 0] = decal->color4f[0][0] * alpha;
11293                 c4f[ 1] = decal->color4f[0][1] * alpha;
11294                 c4f[ 2] = decal->color4f[0][2] * alpha;
11295                 c4f[ 3] = 1;
11296                 c4f[ 4] = decal->color4f[1][0] * alpha;
11297                 c4f[ 5] = decal->color4f[1][1] * alpha;
11298                 c4f[ 6] = decal->color4f[1][2] * alpha;
11299                 c4f[ 7] = 1;
11300                 c4f[ 8] = decal->color4f[2][0] * alpha;
11301                 c4f[ 9] = decal->color4f[2][1] * alpha;
11302                 c4f[10] = decal->color4f[2][2] * alpha;
11303                 c4f[11] = 1;
11304
11305                 t2f[0] = decal->texcoord2f[0][0];
11306                 t2f[1] = decal->texcoord2f[0][1];
11307                 t2f[2] = decal->texcoord2f[1][0];
11308                 t2f[3] = decal->texcoord2f[1][1];
11309                 t2f[4] = decal->texcoord2f[2][0];
11310                 t2f[5] = decal->texcoord2f[2][1];
11311
11312                 // update vertex positions for animated models
11313                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11314                 {
11315                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11316                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11317                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11318                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11319                 }
11320                 else
11321                 {
11322                         VectorCopy(decal->vertex3f[0], v3f);
11323                         VectorCopy(decal->vertex3f[1], v3f + 3);
11324                         VectorCopy(decal->vertex3f[2], v3f + 6);
11325                 }
11326
11327                 if (r_refdef.fogenabled)
11328                 {
11329                         alpha = RSurf_FogVertex(v3f);
11330                         VectorScale(c4f, alpha, c4f);
11331                         alpha = RSurf_FogVertex(v3f + 3);
11332                         VectorScale(c4f + 4, alpha, c4f + 4);
11333                         alpha = RSurf_FogVertex(v3f + 6);
11334                         VectorScale(c4f + 8, alpha, c4f + 8);
11335                 }
11336
11337                 v3f += 9;
11338                 c4f += 12;
11339                 t2f += 6;
11340                 numtris++;
11341         }
11342
11343         if (numtris > 0)
11344         {
11345                 r_refdef.stats.drawndecals += numtris;
11346
11347                 // now render the decals all at once
11348                 // (this assumes they all use one particle font texture!)
11349                 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);
11350 //              R_Mesh_ResetTextureState();
11351                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11352                 GL_DepthMask(false);
11353                 GL_DepthRange(0, 1);
11354                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11355                 GL_DepthTest(true);
11356                 GL_CullFace(GL_NONE);
11357                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11358                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11359                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11360         }
11361 }
11362
11363 static void R_DrawModelDecals(void)
11364 {
11365         int i, numdecals;
11366
11367         // fade faster when there are too many decals
11368         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11369         for (i = 0;i < r_refdef.scene.numentities;i++)
11370                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11371
11372         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11373         for (i = 0;i < r_refdef.scene.numentities;i++)
11374                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11375                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11376
11377         R_DecalSystem_ApplySplatEntitiesQueue();
11378
11379         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11380         for (i = 0;i < r_refdef.scene.numentities;i++)
11381                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11382
11383         r_refdef.stats.totaldecals += numdecals;
11384
11385         if (r_showsurfaces.integer)
11386                 return;
11387
11388         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11389
11390         for (i = 0;i < r_refdef.scene.numentities;i++)
11391         {
11392                 if (!r_refdef.viewcache.entityvisible[i])
11393                         continue;
11394                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11395                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11396         }
11397 }
11398
11399 extern cvar_t mod_collision_bih;
11400 void R_DrawDebugModel(void)
11401 {
11402         entity_render_t *ent = rsurface.entity;
11403         int i, j, k, l, flagsmask;
11404         const msurface_t *surface;
11405         dp_model_t *model = ent->model;
11406         vec3_t v;
11407
11408         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11409                 return;
11410
11411         if (r_showoverdraw.value > 0)
11412         {
11413                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11414                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11415                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11416                 GL_DepthTest(false);
11417                 GL_DepthMask(false);
11418                 GL_DepthRange(0, 1);
11419                 GL_BlendFunc(GL_ONE, GL_ONE);
11420                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11421                 {
11422                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11423                                 continue;
11424                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11425                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11426                         {
11427                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11428                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11429                                 if (!rsurface.texture->currentlayers->depthmask)
11430                                         GL_Color(c, 0, 0, 1.0f);
11431                                 else if (ent == r_refdef.scene.worldentity)
11432                                         GL_Color(c, c, c, 1.0f);
11433                                 else
11434                                         GL_Color(0, c, 0, 1.0f);
11435                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11436                                 RSurf_DrawBatch();
11437                         }
11438                 }
11439                 rsurface.texture = NULL;
11440         }
11441
11442         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11443
11444 //      R_Mesh_ResetTextureState();
11445         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11446         GL_DepthRange(0, 1);
11447         GL_DepthTest(!r_showdisabledepthtest.integer);
11448         GL_DepthMask(false);
11449         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11450
11451         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11452         {
11453                 int triangleindex;
11454                 int bihleafindex;
11455                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11456                 const q3mbrush_t *brush;
11457                 const bih_t *bih = &model->collision_bih;
11458                 const bih_leaf_t *bihleaf;
11459                 float vertex3f[3][3];
11460                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11461                 cullbox = false;
11462                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11463                 {
11464                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11465                                 continue;
11466                         switch (bihleaf->type)
11467                         {
11468                         case BIH_BRUSH:
11469                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11470                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11471                                 {
11472                                         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);
11473                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11474                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11475                                 }
11476                                 break;
11477                         case BIH_COLLISIONTRIANGLE:
11478                                 triangleindex = bihleaf->itemindex;
11479                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11480                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11481                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11482                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11483                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11484                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11485                                 break;
11486                         case BIH_RENDERTRIANGLE:
11487                                 triangleindex = bihleaf->itemindex;
11488                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11489                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11490                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11491                                 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);
11492                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11493                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11494                                 break;
11495                         }
11496                 }
11497         }
11498
11499         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11500
11501 #ifndef USE_GLES2
11502         if (r_showtris.integer && qglPolygonMode)
11503         {
11504                 if (r_showdisabledepthtest.integer)
11505                 {
11506                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11507                         GL_DepthMask(false);
11508                 }
11509                 else
11510                 {
11511                         GL_BlendFunc(GL_ONE, GL_ZERO);
11512                         GL_DepthMask(true);
11513                 }
11514                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11515                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11516                 {
11517                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11518                                 continue;
11519                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11520                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11521                         {
11522                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11523                                 if (!rsurface.texture->currentlayers->depthmask)
11524                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11525                                 else if (ent == r_refdef.scene.worldentity)
11526                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11527                                 else
11528                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11529                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11530                                 RSurf_DrawBatch();
11531                         }
11532                 }
11533                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11534                 rsurface.texture = NULL;
11535         }
11536
11537         if (r_shownormals.value != 0 && qglBegin)
11538         {
11539                 if (r_showdisabledepthtest.integer)
11540                 {
11541                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11542                         GL_DepthMask(false);
11543                 }
11544                 else
11545                 {
11546                         GL_BlendFunc(GL_ONE, GL_ZERO);
11547                         GL_DepthMask(true);
11548                 }
11549                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11550                 {
11551                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11552                                 continue;
11553                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11554                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11555                         {
11556                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11557                                 qglBegin(GL_LINES);
11558                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11559                                 {
11560                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11561                                         {
11562                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11563                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11564                                                 qglVertex3f(v[0], v[1], v[2]);
11565                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11566                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11567                                                 qglVertex3f(v[0], v[1], v[2]);
11568                                         }
11569                                 }
11570                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11571                                 {
11572                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11573                                         {
11574                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11575                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11576                                                 qglVertex3f(v[0], v[1], v[2]);
11577                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11578                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11579                                                 qglVertex3f(v[0], v[1], v[2]);
11580                                         }
11581                                 }
11582                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11583                                 {
11584                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11585                                         {
11586                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11587                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11588                                                 qglVertex3f(v[0], v[1], v[2]);
11589                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11590                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11591                                                 qglVertex3f(v[0], v[1], v[2]);
11592                                         }
11593                                 }
11594                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11595                                 {
11596                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11597                                         {
11598                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11599                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11600                                                 qglVertex3f(v[0], v[1], v[2]);
11601                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11602                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11603                                                 qglVertex3f(v[0], v[1], v[2]);
11604                                         }
11605                                 }
11606                                 qglEnd();
11607                                 CHECKGLERROR
11608                         }
11609                 }
11610                 rsurface.texture = NULL;
11611         }
11612 #endif
11613 }
11614
11615 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11616 int r_maxsurfacelist = 0;
11617 const msurface_t **r_surfacelist = NULL;
11618 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11619 {
11620         int i, j, endj, flagsmask;
11621         dp_model_t *model = r_refdef.scene.worldmodel;
11622         msurface_t *surfaces;
11623         unsigned char *update;
11624         int numsurfacelist = 0;
11625         if (model == NULL)
11626                 return;
11627
11628         if (r_maxsurfacelist < model->num_surfaces)
11629         {
11630                 r_maxsurfacelist = model->num_surfaces;
11631                 if (r_surfacelist)
11632                         Mem_Free((msurface_t**)r_surfacelist);
11633                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11634         }
11635
11636         RSurf_ActiveWorldEntity();
11637
11638         surfaces = model->data_surfaces;
11639         update = model->brushq1.lightmapupdateflags;
11640
11641         // update light styles on this submodel
11642         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11643         {
11644                 model_brush_lightstyleinfo_t *style;
11645                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11646                 {
11647                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11648                         {
11649                                 int *list = style->surfacelist;
11650                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11651                                 for (j = 0;j < style->numsurfaces;j++)
11652                                         update[list[j]] = true;
11653                         }
11654                 }
11655         }
11656
11657         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11658
11659         if (debug)
11660         {
11661                 R_DrawDebugModel();
11662                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11663                 return;
11664         }
11665
11666         rsurface.lightmaptexture = NULL;
11667         rsurface.deluxemaptexture = NULL;
11668         rsurface.uselightmaptexture = false;
11669         rsurface.texture = NULL;
11670         rsurface.rtlight = NULL;
11671         numsurfacelist = 0;
11672         // add visible surfaces to draw list
11673         for (i = 0;i < model->nummodelsurfaces;i++)
11674         {
11675                 j = model->sortedmodelsurfaces[i];
11676                 if (r_refdef.viewcache.world_surfacevisible[j])
11677                         r_surfacelist[numsurfacelist++] = surfaces + j;
11678         }
11679         // update lightmaps if needed
11680         if (model->brushq1.firstrender)
11681         {
11682                 model->brushq1.firstrender = false;
11683                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11684                         if (update[j])
11685                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11686         }
11687         else if (update)
11688         {
11689                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11690                         if (r_refdef.viewcache.world_surfacevisible[j])
11691                                 if (update[j])
11692                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11693         }
11694         // don't do anything if there were no surfaces
11695         if (!numsurfacelist)
11696         {
11697                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11698                 return;
11699         }
11700         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11701
11702         // add to stats if desired
11703         if (r_speeds.integer && !skysurfaces && !depthonly)
11704         {
11705                 r_refdef.stats.world_surfaces += numsurfacelist;
11706                 for (j = 0;j < numsurfacelist;j++)
11707                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11708         }
11709
11710         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11711 }
11712
11713 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11714 {
11715         int i, j, endj, flagsmask;
11716         dp_model_t *model = ent->model;
11717         msurface_t *surfaces;
11718         unsigned char *update;
11719         int numsurfacelist = 0;
11720         if (model == NULL)
11721                 return;
11722
11723         if (r_maxsurfacelist < model->num_surfaces)
11724         {
11725                 r_maxsurfacelist = model->num_surfaces;
11726                 if (r_surfacelist)
11727                         Mem_Free((msurface_t **)r_surfacelist);
11728                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11729         }
11730
11731         // if the model is static it doesn't matter what value we give for
11732         // wantnormals and wanttangents, so this logic uses only rules applicable
11733         // to a model, knowing that they are meaningless otherwise
11734         if (ent == r_refdef.scene.worldentity)
11735                 RSurf_ActiveWorldEntity();
11736         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11737                 RSurf_ActiveModelEntity(ent, false, false, false);
11738         else if (prepass)
11739                 RSurf_ActiveModelEntity(ent, true, true, true);
11740         else if (depthonly)
11741         {
11742                 switch (vid.renderpath)
11743                 {
11744                 case RENDERPATH_GL20:
11745                 case RENDERPATH_D3D9:
11746                 case RENDERPATH_D3D10:
11747                 case RENDERPATH_D3D11:
11748                 case RENDERPATH_SOFT:
11749                 case RENDERPATH_GLES2:
11750                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11751                         break;
11752                 case RENDERPATH_GL11:
11753                 case RENDERPATH_GL13:
11754                 case RENDERPATH_GLES1:
11755                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11756                         break;
11757                 }
11758         }
11759         else
11760         {
11761                 switch (vid.renderpath)
11762                 {
11763                 case RENDERPATH_GL20:
11764                 case RENDERPATH_D3D9:
11765                 case RENDERPATH_D3D10:
11766                 case RENDERPATH_D3D11:
11767                 case RENDERPATH_SOFT:
11768                 case RENDERPATH_GLES2:
11769                         RSurf_ActiveModelEntity(ent, true, true, false);
11770                         break;
11771                 case RENDERPATH_GL11:
11772                 case RENDERPATH_GL13:
11773                 case RENDERPATH_GLES1:
11774                         RSurf_ActiveModelEntity(ent, true, false, false);
11775                         break;
11776                 }
11777         }
11778
11779         surfaces = model->data_surfaces;
11780         update = model->brushq1.lightmapupdateflags;
11781
11782         // update light styles
11783         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11784         {
11785                 model_brush_lightstyleinfo_t *style;
11786                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11787                 {
11788                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11789                         {
11790                                 int *list = style->surfacelist;
11791                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11792                                 for (j = 0;j < style->numsurfaces;j++)
11793                                         update[list[j]] = true;
11794                         }
11795                 }
11796         }
11797
11798         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11799
11800         if (debug)
11801         {
11802                 R_DrawDebugModel();
11803                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11804                 return;
11805         }
11806
11807         rsurface.lightmaptexture = NULL;
11808         rsurface.deluxemaptexture = NULL;
11809         rsurface.uselightmaptexture = false;
11810         rsurface.texture = NULL;
11811         rsurface.rtlight = NULL;
11812         numsurfacelist = 0;
11813         // add visible surfaces to draw list
11814         for (i = 0;i < model->nummodelsurfaces;i++)
11815                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11816         // don't do anything if there were no surfaces
11817         if (!numsurfacelist)
11818         {
11819                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11820                 return;
11821         }
11822         // update lightmaps if needed
11823         if (update)
11824         {
11825                 int updated = 0;
11826                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11827                 {
11828                         if (update[j])
11829                         {
11830                                 updated++;
11831                                 R_BuildLightMap(ent, surfaces + j);
11832                         }
11833                 }
11834         }
11835         if (update)
11836                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11837                         if (update[j])
11838                                 R_BuildLightMap(ent, surfaces + j);
11839         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11840
11841         // add to stats if desired
11842         if (r_speeds.integer && !skysurfaces && !depthonly)
11843         {
11844                 r_refdef.stats.entities_surfaces += numsurfacelist;
11845                 for (j = 0;j < numsurfacelist;j++)
11846                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11847         }
11848
11849         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850 }
11851
11852 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11853 {
11854         static texture_t texture;
11855         static msurface_t surface;
11856         const msurface_t *surfacelist = &surface;
11857
11858         // fake enough texture and surface state to render this geometry
11859
11860         texture.update_lastrenderframe = -1; // regenerate this texture
11861         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11862         texture.currentskinframe = skinframe;
11863         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11864         texture.offsetmapping = OFFSETMAPPING_OFF;
11865         texture.offsetscale = 1;
11866         texture.specularscalemod = 1;
11867         texture.specularpowermod = 1;
11868
11869         surface.texture = &texture;
11870         surface.num_triangles = numtriangles;
11871         surface.num_firsttriangle = firsttriangle;
11872         surface.num_vertices = numvertices;
11873         surface.num_firstvertex = firstvertex;
11874
11875         // now render it
11876         rsurface.texture = R_GetCurrentTexture(surface.texture);
11877         rsurface.lightmaptexture = NULL;
11878         rsurface.deluxemaptexture = NULL;
11879         rsurface.uselightmaptexture = false;
11880         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11881 }
11882
11883 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)
11884 {
11885         static msurface_t surface;
11886         const msurface_t *surfacelist = &surface;
11887
11888         // fake enough texture and surface state to render this geometry
11889         surface.texture = texture;
11890         surface.num_triangles = numtriangles;
11891         surface.num_firsttriangle = firsttriangle;
11892         surface.num_vertices = numvertices;
11893         surface.num_firstvertex = firstvertex;
11894
11895         // now render it
11896         rsurface.texture = R_GetCurrentTexture(surface.texture);
11897         rsurface.lightmaptexture = NULL;
11898         rsurface.deluxemaptexture = NULL;
11899         rsurface.uselightmaptexture = false;
11900         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11901 }