]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
make sure another way it never calculates 0^0
[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
211 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"};
212
213 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"};
214
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
216
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
218
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 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"};
221
222 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."};
223
224 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)"};
225
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
228
229 extern qboolean v_flipped_state;
230
231 static struct r_bloomstate_s
232 {
233         qboolean enabled;
234         qboolean hdr;
235
236         int bloomwidth, bloomheight;
237
238         textype_t texturetype;
239         int viewfbo; // used to check if r_viewfbo cvar has changed
240
241         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244
245         int screentexturewidth, screentextureheight;
246         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247
248         int bloomtexturewidth, bloomtextureheight;
249         rtexture_t *texture_bloom;
250
251         // arrays for rendering the screen passes
252         float screentexcoord2f[8];
253         float bloomtexcoord2f[8];
254         float offsettexcoord2f[8];
255
256         r_viewport_t viewport;
257 }
258 r_bloomstate;
259
260 r_waterstate_t r_waterstate;
261
262 /// shadow volume bsp struct with automatically growing nodes buffer
263 svbsp_t r_svbsp;
264
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
278
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
281 {
282         char basename[64];
283         rtexture_t *texture;
284 }
285 cubemapinfo_t;
286
287 int r_texture_numcubemaps;
288 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
289
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
293
294 typedef struct r_qwskincache_s
295 {
296         char name[MAX_QPATH];
297         skinframe_t *skinframe;
298 }
299 r_qwskincache_t;
300
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
303
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
308 {
309         0, 0, 0,
310         1, 0, 0,
311         1, 1, 0,
312         0, 1, 0
313 };
314 const float r_d3dscreenvertex3f[12] =
315 {
316         0, 1, 0,
317         1, 1, 0,
318         1, 0, 0,
319         0, 0, 0
320 };
321
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = in[0] * r;
328                 out[1] = in[1] * g;
329                 out[2] = in[2] * b;
330                 out[3] = in[3];
331                 in += 4;
332                 out += 4;
333         }
334 }
335
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 {
338         int i;
339         for (i = 0;i < verts;i++)
340         {
341                 out[0] = r;
342                 out[1] = g;
343                 out[2] = b;
344                 out[3] = a;
345                 out += 4;
346         }
347 }
348
349 // FIXME: move this to client?
350 void FOG_clear(void)
351 {
352         if (gamemode == GAME_NEHAHRA)
353         {
354                 Cvar_Set("gl_fogenable", "0");
355                 Cvar_Set("gl_fogdensity", "0.2");
356                 Cvar_Set("gl_fogred", "0.3");
357                 Cvar_Set("gl_foggreen", "0.3");
358                 Cvar_Set("gl_fogblue", "0.3");
359         }
360         r_refdef.fog_density = 0;
361         r_refdef.fog_red = 0;
362         r_refdef.fog_green = 0;
363         r_refdef.fog_blue = 0;
364         r_refdef.fog_alpha = 1;
365         r_refdef.fog_start = 0;
366         r_refdef.fog_end = 16384;
367         r_refdef.fog_height = 1<<30;
368         r_refdef.fog_fadedepth = 128;
369         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 }
371
372 static void R_BuildBlankTextures(void)
373 {
374         unsigned char data[4];
375         data[2] = 128; // normal X
376         data[1] = 128; // normal Y
377         data[0] = 255; // normal Z
378         data[3] = 128; // height
379         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 255;
381         data[1] = 255;
382         data[2] = 255;
383         data[3] = 255;
384         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 128;
386         data[1] = 128;
387         data[2] = 128;
388         data[3] = 255;
389         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 0;
391         data[1] = 0;
392         data[2] = 0;
393         data[3] = 255;
394         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildNoTexture(void)
398 {
399         int x, y;
400         unsigned char pix[16][16][4];
401         // this makes a light grey/dark grey checkerboard texture
402         for (y = 0;y < 16;y++)
403         {
404                 for (x = 0;x < 16;x++)
405                 {
406                         if ((y < 8) ^ (x < 8))
407                         {
408                                 pix[y][x][0] = 128;
409                                 pix[y][x][1] = 128;
410                                 pix[y][x][2] = 128;
411                                 pix[y][x][3] = 255;
412                         }
413                         else
414                         {
415                                 pix[y][x][0] = 64;
416                                 pix[y][x][1] = 64;
417                                 pix[y][x][2] = 64;
418                                 pix[y][x][3] = 255;
419                         }
420                 }
421         }
422         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 }
424
425 static void R_BuildWhiteCube(void)
426 {
427         unsigned char data[6*1*1*4];
428         memset(data, 255, sizeof(data));
429         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 }
431
432 static void R_BuildNormalizationCube(void)
433 {
434         int x, y, side;
435         vec3_t v;
436         vec_t s, t, intensity;
437 #define NORMSIZE 64
438         unsigned char *data;
439         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440         for (side = 0;side < 6;side++)
441         {
442                 for (y = 0;y < NORMSIZE;y++)
443                 {
444                         for (x = 0;x < NORMSIZE;x++)
445                         {
446                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 switch(side)
449                                 {
450                                 default:
451                                 case 0:
452                                         v[0] = 1;
453                                         v[1] = -t;
454                                         v[2] = -s;
455                                         break;
456                                 case 1:
457                                         v[0] = -1;
458                                         v[1] = -t;
459                                         v[2] = s;
460                                         break;
461                                 case 2:
462                                         v[0] = s;
463                                         v[1] = 1;
464                                         v[2] = t;
465                                         break;
466                                 case 3:
467                                         v[0] = s;
468                                         v[1] = -1;
469                                         v[2] = -t;
470                                         break;
471                                 case 4:
472                                         v[0] = s;
473                                         v[1] = -t;
474                                         v[2] = 1;
475                                         break;
476                                 case 5:
477                                         v[0] = -s;
478                                         v[1] = -t;
479                                         v[2] = -1;
480                                         break;
481                                 }
482                                 intensity = 127.0f / sqrt(DotProduct(v, v));
483                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486                                 data[((side*64+y)*64+x)*4+3] = 255;
487                         }
488                 }
489         }
490         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491         Mem_Free(data);
492 }
493
494 static void R_BuildFogTexture(void)
495 {
496         int x, b;
497 #define FOGWIDTH 256
498         unsigned char data1[FOGWIDTH][4];
499         //unsigned char data2[FOGWIDTH][4];
500         double d, r, alpha;
501
502         r_refdef.fogmasktable_start = r_refdef.fog_start;
503         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504         r_refdef.fogmasktable_range = r_refdef.fogrange;
505         r_refdef.fogmasktable_density = r_refdef.fog_density;
506
507         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509         {
510                 d = (x * r - r_refdef.fogmasktable_start);
511                 if(developer_extra.integer)
512                         Con_DPrintf("%f ", d);
513                 d = max(0, d);
514                 if (r_fog_exp2.integer)
515                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516                 else
517                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518                 if(developer_extra.integer)
519                         Con_DPrintf(" : %f ", alpha);
520                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521                 if(developer_extra.integer)
522                         Con_DPrintf(" = %f\n", alpha);
523                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524         }
525
526         for (x = 0;x < FOGWIDTH;x++)
527         {
528                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529                 data1[x][0] = b;
530                 data1[x][1] = b;
531                 data1[x][2] = b;
532                 data1[x][3] = 255;
533                 //data2[x][0] = 255 - b;
534                 //data2[x][1] = 255 - b;
535                 //data2[x][2] = 255 - b;
536                 //data2[x][3] = 255;
537         }
538         if (r_texture_fogattenuation)
539         {
540                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542         }
543         else
544         {
545                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547         }
548 }
549
550 static void R_BuildFogHeightTexture(void)
551 {
552         unsigned char *inpixels;
553         int size;
554         int x;
555         int y;
556         int j;
557         float c[4];
558         float f;
559         inpixels = NULL;
560         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561         if (r_refdef.fogheighttexturename[0])
562                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563         if (!inpixels)
564         {
565                 r_refdef.fog_height_tablesize = 0;
566                 if (r_texture_fogheighttexture)
567                         R_FreeTexture(r_texture_fogheighttexture);
568                 r_texture_fogheighttexture = NULL;
569                 if (r_refdef.fog_height_table2d)
570                         Mem_Free(r_refdef.fog_height_table2d);
571                 r_refdef.fog_height_table2d = NULL;
572                 if (r_refdef.fog_height_table1d)
573                         Mem_Free(r_refdef.fog_height_table1d);
574                 r_refdef.fog_height_table1d = NULL;
575                 return;
576         }
577         size = image_width;
578         r_refdef.fog_height_tablesize = size;
579         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582         Mem_Free(inpixels);
583         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
584         // average fog color table accounting for every fog layer between a point
585         // and the camera.  (Note: attenuation is handled separately!)
586         for (y = 0;y < size;y++)
587         {
588                 for (x = 0;x < size;x++)
589                 {
590                         Vector4Clear(c);
591                         f = 0;
592                         if (x < y)
593                         {
594                                 for (j = x;j <= y;j++)
595                                 {
596                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597                                         f++;
598                                 }
599                         }
600                         else
601                         {
602                                 for (j = x;j >= y;j--)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         f = 1.0f / f;
609                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613                 }
614         }
615         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 }
617
618 //=======================================================================================================================================================
619
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
622 ;
623
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
626 ;
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *vertexfilename;
643         const char *geometryfilename;
644         const char *fragmentfilename;
645         const char *pretext;
646         const char *name;
647 }
648 shadermodeinfo_t;
649
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {
653         {"#define USEDIFFUSE\n", " diffuse"},
654         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655         {"#define USEVIEWTINT\n", " viewtint"},
656         {"#define USECOLORMAPPING\n", " colormapping"},
657         {"#define USESATURATION\n", " saturation"},
658         {"#define USEFOGINSIDE\n", " foginside"},
659         {"#define USEFOGOUTSIDE\n", " fogoutside"},
660         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662         {"#define USEGAMMARAMPS\n", " gammaramps"},
663         {"#define USECUBEFILTER\n", " cubefilter"},
664         {"#define USEGLOW\n", " glow"},
665         {"#define USEBLOOM\n", " bloom"},
666         {"#define USESPECULAR\n", " specular"},
667         {"#define USEPOSTPROCESSING\n", " postprocessing"},
668         {"#define USEREFLECTION\n", " reflection"},
669         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683         {"#define USETRIPPY\n", " trippy"},
684 };
685
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 };
708
709 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 };
730
731 struct r_glsl_permutation_s;
732 typedef struct r_glsl_permutation_s
733 {
734         /// hash lookup data
735         struct r_glsl_permutation_s *hashnext;
736         unsigned int mode;
737         unsigned int permutation;
738
739         /// indicates if we have tried compiling this permutation already
740         qboolean compiled;
741         /// 0 if compilation failed
742         int program;
743         // texture units assigned to each detected uniform
744         int tex_Texture_First;
745         int tex_Texture_Second;
746         int tex_Texture_GammaRamps;
747         int tex_Texture_Normal;
748         int tex_Texture_Color;
749         int tex_Texture_Gloss;
750         int tex_Texture_Glow;
751         int tex_Texture_SecondaryNormal;
752         int tex_Texture_SecondaryColor;
753         int tex_Texture_SecondaryGloss;
754         int tex_Texture_SecondaryGlow;
755         int tex_Texture_Pants;
756         int tex_Texture_Shirt;
757         int tex_Texture_FogHeightTexture;
758         int tex_Texture_FogMask;
759         int tex_Texture_Lightmap;
760         int tex_Texture_Deluxemap;
761         int tex_Texture_Attenuation;
762         int tex_Texture_Cube;
763         int tex_Texture_Refraction;
764         int tex_Texture_Reflection;
765         int tex_Texture_ShadowMap2D;
766         int tex_Texture_CubeProjection;
767         int tex_Texture_ScreenDepth;
768         int tex_Texture_ScreenNormalMap;
769         int tex_Texture_ScreenDiffuse;
770         int tex_Texture_ScreenSpecular;
771         int tex_Texture_ReflectMask;
772         int tex_Texture_ReflectCube;
773         int tex_Texture_BounceGrid;
774         /// locations of detected uniforms in program object, or -1 if not found
775         int loc_Texture_First;
776         int loc_Texture_Second;
777         int loc_Texture_GammaRamps;
778         int loc_Texture_Normal;
779         int loc_Texture_Color;
780         int loc_Texture_Gloss;
781         int loc_Texture_Glow;
782         int loc_Texture_SecondaryNormal;
783         int loc_Texture_SecondaryColor;
784         int loc_Texture_SecondaryGloss;
785         int loc_Texture_SecondaryGlow;
786         int loc_Texture_Pants;
787         int loc_Texture_Shirt;
788         int loc_Texture_FogHeightTexture;
789         int loc_Texture_FogMask;
790         int loc_Texture_Lightmap;
791         int loc_Texture_Deluxemap;
792         int loc_Texture_Attenuation;
793         int loc_Texture_Cube;
794         int loc_Texture_Refraction;
795         int loc_Texture_Reflection;
796         int loc_Texture_ShadowMap2D;
797         int loc_Texture_CubeProjection;
798         int loc_Texture_ScreenDepth;
799         int loc_Texture_ScreenNormalMap;
800         int loc_Texture_ScreenDiffuse;
801         int loc_Texture_ScreenSpecular;
802         int loc_Texture_ReflectMask;
803         int loc_Texture_ReflectCube;
804         int loc_Texture_BounceGrid;
805         int loc_Alpha;
806         int loc_BloomBlur_Parameters;
807         int loc_ClientTime;
808         int loc_Color_Ambient;
809         int loc_Color_Diffuse;
810         int loc_Color_Specular;
811         int loc_Color_Glow;
812         int loc_Color_Pants;
813         int loc_Color_Shirt;
814         int loc_DeferredColor_Ambient;
815         int loc_DeferredColor_Diffuse;
816         int loc_DeferredColor_Specular;
817         int loc_DeferredMod_Diffuse;
818         int loc_DeferredMod_Specular;
819         int loc_DistortScaleRefractReflect;
820         int loc_EyePosition;
821         int loc_FogColor;
822         int loc_FogHeightFade;
823         int loc_FogPlane;
824         int loc_FogPlaneViewDist;
825         int loc_FogRangeRecip;
826         int loc_LightColor;
827         int loc_LightDir;
828         int loc_LightPosition;
829         int loc_OffsetMapping_ScaleSteps;
830         int loc_OffsetMapping_LodDistance;
831         int loc_PixelSize;
832         int loc_ReflectColor;
833         int loc_ReflectFactor;
834         int loc_ReflectOffset;
835         int loc_RefractColor;
836         int loc_Saturation;
837         int loc_ScreenCenterRefractReflect;
838         int loc_ScreenScaleRefractReflect;
839         int loc_ScreenToDepth;
840         int loc_ShadowMap_Parameters;
841         int loc_ShadowMap_TextureScale;
842         int loc_SpecularPower;
843         int loc_UserVec1;
844         int loc_UserVec2;
845         int loc_UserVec3;
846         int loc_UserVec4;
847         int loc_ViewTintColor;
848         int loc_ViewToLight;
849         int loc_ModelToLight;
850         int loc_TexMatrix;
851         int loc_BackgroundTexMatrix;
852         int loc_ModelViewProjectionMatrix;
853         int loc_ModelViewMatrix;
854         int loc_PixelToScreenTexCoord;
855         int loc_ModelToReflectCube;
856         int loc_ShadowMapMatrix;
857         int loc_BloomColorSubtract;
858         int loc_NormalmapScrollBlend;
859         int loc_BounceGridMatrix;
860         int loc_BounceGridIntensity;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879 };
880 #define SHADERSTATICPARMS_COUNT 8
881
882 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
883 static int shaderstaticparms_count = 0;
884
885 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
886 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
887 qboolean R_CompileShader_CheckStaticParms(void)
888 {
889         static int r_compileshader_staticparms_save[1];
890         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
891         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
892
893         // detect all
894         if (r_glsl_saturation_redcompensate.integer)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
896         if (r_glsl_vertextextureblend_usebothalphas.integer)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
898         if (r_shadow_glossexact.integer)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
900         if (r_glsl_postprocess.integer)
901         {
902                 if (r_glsl_postprocess_uservec1_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
904                 if (r_glsl_postprocess_uservec2_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
906                 if (r_glsl_postprocess_uservec3_enable.integer)
907                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
908                 if (r_glsl_postprocess_uservec4_enable.integer)
909                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
910         }
911         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
913         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
914 }
915
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
919         else \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
922 {
923         shaderstaticparms_count = 0;
924
925         // emit all
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
934 }
935
936 /// information about each possible shader permutation
937 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
938 /// currently selected permutation
939 r_glsl_permutation_t *r_glsl_permutation;
940 /// storage for permutations linked in the hash table
941 memexpandablearray_t r_glsl_permutationarray;
942
943 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
944 {
945         //unsigned int hashdepth = 0;
946         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
947         r_glsl_permutation_t *p;
948         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
949         {
950                 if (p->mode == mode && p->permutation == permutation)
951                 {
952                         //if (hashdepth > 10)
953                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954                         return p;
955                 }
956                 //hashdepth++;
957         }
958         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
959         p->mode = mode;
960         p->permutation = permutation;
961         p->hashnext = r_glsl_permutationhash[mode][hashindex];
962         r_glsl_permutationhash[mode][hashindex] = p;
963         //if (hashdepth > 10)
964         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
965         return p;
966 }
967
968 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
969 {
970         char *shaderstring;
971         if (!filename || !filename[0])
972                 return NULL;
973         if (!strcmp(filename, "glsl/default.glsl"))
974         {
975                 if (!glslshaderstring)
976                 {
977                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978                         if (glslshaderstring)
979                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
980                         else
981                                 glslshaderstring = (char *)builtinshaderstring;
982                 }
983                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
984                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
985                 return shaderstring;
986         }
987         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988         if (shaderstring)
989         {
990                 if (printfromdisknotice)
991                         Con_DPrintf("from disk %s... ", filename);
992                 return shaderstring;
993         }
994         return shaderstring;
995 }
996
997 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
998 {
999         int i;
1000         int sampler;
1001         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1002         char *vertexstring, *geometrystring, *fragmentstring;
1003         char permutationname[256];
1004         int vertstrings_count = 0;
1005         int geomstrings_count = 0;
1006         int fragstrings_count = 0;
1007         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010
1011         if (p->compiled)
1012                 return;
1013         p->compiled = true;
1014         p->program = 0;
1015
1016         permutationname[0] = 0;
1017         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1018         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1019         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1020
1021         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1022
1023         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1024         if(vid.support.gl20shaders130)
1025         {
1026                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1027                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1028                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1029                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1030                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1031                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1032         }
1033
1034         // the first pretext is which type of shader to compile as
1035         // (later these will all be bound together as a program object)
1036         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1037         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1038         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1039
1040         // the second pretext is the mode (for example a light source)
1041         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1042         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1043         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1044         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1045
1046         // now add all the permutation pretexts
1047         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1048         {
1049                 if (permutation & (1<<i))
1050                 {
1051                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1052                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1055                 }
1056                 else
1057                 {
1058                         // keep line numbers correct
1059                         vertstrings_list[vertstrings_count++] = "\n";
1060                         geomstrings_list[geomstrings_count++] = "\n";
1061                         fragstrings_list[fragstrings_count++] = "\n";
1062                 }
1063         }
1064
1065         // add static parms
1066         R_CompileShader_AddStaticParms(mode, permutation);
1067         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1068         vertstrings_count += shaderstaticparms_count;
1069         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         geomstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         fragstrings_count += shaderstaticparms_count;
1073
1074         // now append the shader text itself
1075         vertstrings_list[vertstrings_count++] = vertexstring;
1076         geomstrings_list[geomstrings_count++] = geometrystring;
1077         fragstrings_list[fragstrings_count++] = fragmentstring;
1078
1079         // if any sources were NULL, clear the respective list
1080         if (!vertexstring)
1081                 vertstrings_count = 0;
1082         if (!geometrystring)
1083                 geomstrings_count = 0;
1084         if (!fragmentstring)
1085                 fragstrings_count = 0;
1086
1087         // compile the shader program
1088         if (vertstrings_count + geomstrings_count + fragstrings_count)
1089                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1090         if (p->program)
1091         {
1092                 CHECKGLERROR
1093                 qglUseProgram(p->program);CHECKGLERROR
1094                 // look up all the uniform variable names we care about, so we don't
1095                 // have to look them up every time we set them
1096
1097                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1098                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1099                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1100                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1101                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1102                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1103                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1104                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1105                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1106                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1107                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1108                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1109                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1110                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1111                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1112                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1113                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1114                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1115                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1116                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1117                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1118                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1119                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1120                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1154                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1155                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1156                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1157                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1158                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1159                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1160                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1161                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1162                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1163                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1164                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1165                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1166                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1167                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1168                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1169                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1170                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1171                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1172                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1173                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1174                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1175                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1176                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1177                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1178                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1179                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1180                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1181                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1182                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1183                 // initialize the samplers to refer to the texture units we use
1184                 p->tex_Texture_First = -1;
1185                 p->tex_Texture_Second = -1;
1186                 p->tex_Texture_GammaRamps = -1;
1187                 p->tex_Texture_Normal = -1;
1188                 p->tex_Texture_Color = -1;
1189                 p->tex_Texture_Gloss = -1;
1190                 p->tex_Texture_Glow = -1;
1191                 p->tex_Texture_SecondaryNormal = -1;
1192                 p->tex_Texture_SecondaryColor = -1;
1193                 p->tex_Texture_SecondaryGloss = -1;
1194                 p->tex_Texture_SecondaryGlow = -1;
1195                 p->tex_Texture_Pants = -1;
1196                 p->tex_Texture_Shirt = -1;
1197                 p->tex_Texture_FogHeightTexture = -1;
1198                 p->tex_Texture_FogMask = -1;
1199                 p->tex_Texture_Lightmap = -1;
1200                 p->tex_Texture_Deluxemap = -1;
1201                 p->tex_Texture_Attenuation = -1;
1202                 p->tex_Texture_Cube = -1;
1203                 p->tex_Texture_Refraction = -1;
1204                 p->tex_Texture_Reflection = -1;
1205                 p->tex_Texture_ShadowMap2D = -1;
1206                 p->tex_Texture_CubeProjection = -1;
1207                 p->tex_Texture_ScreenDepth = -1;
1208                 p->tex_Texture_ScreenNormalMap = -1;
1209                 p->tex_Texture_ScreenDiffuse = -1;
1210                 p->tex_Texture_ScreenSpecular = -1;
1211                 p->tex_Texture_ReflectMask = -1;
1212                 p->tex_Texture_ReflectCube = -1;
1213                 p->tex_Texture_BounceGrid = -1;
1214                 sampler = 0;
1215                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1216                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1217                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1218                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1219                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1220                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1221                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1226                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1227                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1228                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1230                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1231                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1232                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1233                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1234                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1235                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1236                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1237                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1244                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1245                 CHECKGLERROR
1246                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1247         }
1248         else
1249                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1250
1251         // free the strings
1252         if (vertexstring)
1253                 Mem_Free(vertexstring);
1254         if (geometrystring)
1255                 Mem_Free(geometrystring);
1256         if (fragmentstring)
1257                 Mem_Free(fragmentstring);
1258 }
1259
1260 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1261 {
1262         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263         if (r_glsl_permutation != perm)
1264         {
1265                 r_glsl_permutation = perm;
1266                 if (!r_glsl_permutation->program)
1267                 {
1268                         if (!r_glsl_permutation->compiled)
1269                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                         if (!r_glsl_permutation->program)
1271                         {
1272                                 // remove features until we find a valid permutation
1273                                 int i;
1274                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275                                 {
1276                                         // reduce i more quickly whenever it would not remove any bits
1277                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278                                         if (!(permutation & j))
1279                                                 continue;
1280                                         permutation -= j;
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         if (!r_glsl_permutation->compiled)
1283                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1284                                         if (r_glsl_permutation->program)
1285                                                 break;
1286                                 }
1287                                 if (i >= SHADERPERMUTATION_COUNT)
1288                                 {
1289                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         qglUseProgram(0);CHECKGLERROR
1292                                         return; // no bit left to clear, entire mode is broken
1293                                 }
1294                         }
1295                 }
1296                 CHECKGLERROR
1297                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1298         }
1299         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1302 }
1303
1304 #ifdef SUPPORTD3D
1305
1306 #ifdef SUPPORTD3D
1307 #include <d3d9.h>
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1310 #endif
1311
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1314 {
1315         /// hash lookup data
1316         struct r_hlsl_permutation_s *hashnext;
1317         unsigned int mode;
1318         unsigned int permutation;
1319
1320         /// indicates if we have tried compiling this permutation already
1321         qboolean compiled;
1322         /// NULL if compilation failed
1323         IDirect3DVertexShader9 *vertexshader;
1324         IDirect3DPixelShader9 *pixelshader;
1325 }
1326 r_hlsl_permutation_t;
1327
1328 typedef enum D3DVSREGISTER_e
1329 {
1330         D3DVSREGISTER_TexMatrix = 0, // float4x4
1331         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335         D3DVSREGISTER_ModelToLight = 20, // float4x4
1336         D3DVSREGISTER_EyePosition = 24,
1337         D3DVSREGISTER_FogPlane = 25,
1338         D3DVSREGISTER_LightDir = 26,
1339         D3DVSREGISTER_LightPosition = 27,
1340 }
1341 D3DVSREGISTER_t;
1342
1343 typedef enum D3DPSREGISTER_e
1344 {
1345         D3DPSREGISTER_Alpha = 0,
1346         D3DPSREGISTER_BloomBlur_Parameters = 1,
1347         D3DPSREGISTER_ClientTime = 2,
1348         D3DPSREGISTER_Color_Ambient = 3,
1349         D3DPSREGISTER_Color_Diffuse = 4,
1350         D3DPSREGISTER_Color_Specular = 5,
1351         D3DPSREGISTER_Color_Glow = 6,
1352         D3DPSREGISTER_Color_Pants = 7,
1353         D3DPSREGISTER_Color_Shirt = 8,
1354         D3DPSREGISTER_DeferredColor_Ambient = 9,
1355         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356         D3DPSREGISTER_DeferredColor_Specular = 11,
1357         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358         D3DPSREGISTER_DeferredMod_Specular = 13,
1359         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360         D3DPSREGISTER_EyePosition = 15, // unused
1361         D3DPSREGISTER_FogColor = 16,
1362         D3DPSREGISTER_FogHeightFade = 17,
1363         D3DPSREGISTER_FogPlane = 18,
1364         D3DPSREGISTER_FogPlaneViewDist = 19,
1365         D3DPSREGISTER_FogRangeRecip = 20,
1366         D3DPSREGISTER_LightColor = 21,
1367         D3DPSREGISTER_LightDir = 22, // unused
1368         D3DPSREGISTER_LightPosition = 23,
1369         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370         D3DPSREGISTER_PixelSize = 25,
1371         D3DPSREGISTER_ReflectColor = 26,
1372         D3DPSREGISTER_ReflectFactor = 27,
1373         D3DPSREGISTER_ReflectOffset = 28,
1374         D3DPSREGISTER_RefractColor = 29,
1375         D3DPSREGISTER_Saturation = 30,
1376         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378         D3DPSREGISTER_ScreenToDepth = 33,
1379         D3DPSREGISTER_ShadowMap_Parameters = 34,
1380         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381         D3DPSREGISTER_SpecularPower = 36,
1382         D3DPSREGISTER_UserVec1 = 37,
1383         D3DPSREGISTER_UserVec2 = 38,
1384         D3DPSREGISTER_UserVec3 = 39,
1385         D3DPSREGISTER_UserVec4 = 40,
1386         D3DPSREGISTER_ViewTintColor = 41,
1387         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388         D3DPSREGISTER_BloomColorSubtract = 43,
1389         D3DPSREGISTER_ViewToLight = 44, // float4x4
1390         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391         D3DPSREGISTER_NormalmapScrollBlend = 52,
1392         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1393         // next at 54
1394 }
1395 D3DPSREGISTER_t;
1396
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1403
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 {
1406         //unsigned int hashdepth = 0;
1407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408         r_hlsl_permutation_t *p;
1409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410         {
1411                 if (p->mode == mode && p->permutation == permutation)
1412                 {
1413                         //if (hashdepth > 10)
1414                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415                         return p;
1416                 }
1417                 //hashdepth++;
1418         }
1419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420         p->mode = mode;
1421         p->permutation = permutation;
1422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423         r_hlsl_permutationhash[mode][hashindex] = p;
1424         //if (hashdepth > 10)
1425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1426         return p;
1427 }
1428
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1430 {
1431         char *shaderstring;
1432         if (!filename || !filename[0])
1433                 return NULL;
1434         if (!strcmp(filename, "hlsl/default.hlsl"))
1435         {
1436                 if (!hlslshaderstring)
1437                 {
1438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439                         if (hlslshaderstring)
1440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441                         else
1442                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1443                 }
1444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446                 return shaderstring;
1447         }
1448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449         if (shaderstring)
1450         {
1451                 if (printfromdisknotice)
1452                         Con_DPrintf("from disk %s... ", filename);
1453                 return shaderstring;
1454         }
1455         return shaderstring;
1456 }
1457
1458 #include <d3dx9.h>
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1461
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 {
1464         DWORD *vsbin = NULL;
1465         DWORD *psbin = NULL;
1466         fs_offset_t vsbinsize;
1467         fs_offset_t psbinsize;
1468 //      IDirect3DVertexShader9 *vs = NULL;
1469 //      IDirect3DPixelShader9 *ps = NULL;
1470         ID3DXBuffer *vslog = NULL;
1471         ID3DXBuffer *vsbuffer = NULL;
1472         ID3DXConstantTable *vsconstanttable = NULL;
1473         ID3DXBuffer *pslog = NULL;
1474         ID3DXBuffer *psbuffer = NULL;
1475         ID3DXConstantTable *psconstanttable = NULL;
1476         int vsresult = 0;
1477         int psresult = 0;
1478         char temp[MAX_INPUTLINE];
1479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480         qboolean debugshader = gl_paranoid.integer != 0;
1481         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1483         if (!debugshader)
1484         {
1485                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1486                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1487         }
1488         if ((!vsbin && vertstring) || (!psbin && fragstring))
1489         {
1490                 const char* dllnames_d3dx9 [] =
1491                 {
1492                         "d3dx9_43.dll",
1493                         "d3dx9_42.dll",
1494                         "d3dx9_41.dll",
1495                         "d3dx9_40.dll",
1496                         "d3dx9_39.dll",
1497                         "d3dx9_38.dll",
1498                         "d3dx9_37.dll",
1499                         "d3dx9_36.dll",
1500                         "d3dx9_35.dll",
1501                         "d3dx9_34.dll",
1502                         "d3dx9_33.dll",
1503                         "d3dx9_32.dll",
1504                         "d3dx9_31.dll",
1505                         "d3dx9_30.dll",
1506                         "d3dx9_29.dll",
1507                         "d3dx9_28.dll",
1508                         "d3dx9_27.dll",
1509                         "d3dx9_26.dll",
1510                         "d3dx9_25.dll",
1511                         "d3dx9_24.dll",
1512                         NULL
1513                 };
1514                 dllhandle_t d3dx9_dll = NULL;
1515                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1516                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1517                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518                 dllfunction_t d3dx9_dllfuncs[] =
1519                 {
1520                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1521                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1522                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1523                         {NULL, NULL}
1524                 };
1525                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1526                 {
1527                         DWORD shaderflags = 0;
1528                         if (debugshader)
1529                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1530                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1531                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1532                         if (vertstring && vertstring[0])
1533                         {
1534                                 if (debugshader)
1535                                 {
1536 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1537 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1538                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1539                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1540                                 }
1541                                 else
1542                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1543                                 if (vsbuffer)
1544                                 {
1545                                         vsbinsize = vsbuffer->GetBufferSize();
1546                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1547                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1548                                         vsbuffer->Release();
1549                                 }
1550                                 if (vslog)
1551                                 {
1552                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1553                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1554                                         vslog->Release();
1555                                 }
1556                         }
1557                         if (fragstring && fragstring[0])
1558                         {
1559                                 if (debugshader)
1560                                 {
1561 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1562 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1563                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1564                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1565                                 }
1566                                 else
1567                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1568                                 if (psbuffer)
1569                                 {
1570                                         psbinsize = psbuffer->GetBufferSize();
1571                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1572                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1573                                         psbuffer->Release();
1574                                 }
1575                                 if (pslog)
1576                                 {
1577                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1578                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1579                                         pslog->Release();
1580                                 }
1581                         }
1582                         Sys_UnloadLibrary(&d3dx9_dll);
1583                 }
1584                 else
1585                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1586         }
1587         if (vsbin && psbin)
1588         {
1589                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1590                 if (FAILED(vsresult))
1591                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1592                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1593                 if (FAILED(psresult))
1594                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1595         }
1596         // free the shader data
1597         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1598         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1599 }
1600
1601 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1602 {
1603         int i;
1604         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1605         int vertstring_length = 0;
1606         int geomstring_length = 0;
1607         int fragstring_length = 0;
1608         char *t;
1609         char *vertexstring, *geometrystring, *fragmentstring;
1610         char *vertstring, *geomstring, *fragstring;
1611         char permutationname[256];
1612         char cachename[256];
1613         int vertstrings_count = 0;
1614         int geomstrings_count = 0;
1615         int fragstrings_count = 0;
1616         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1618         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1619
1620         if (p->compiled)
1621                 return;
1622         p->compiled = true;
1623         p->vertexshader = NULL;
1624         p->pixelshader = NULL;
1625
1626         permutationname[0] = 0;
1627         cachename[0] = 0;
1628         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1629         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1630         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1631
1632         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1633         strlcat(cachename, "hlsl/", sizeof(cachename));
1634
1635         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1636         vertstrings_count = 0;
1637         geomstrings_count = 0;
1638         fragstrings_count = 0;
1639         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1640         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1641         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1642
1643         // the first pretext is which type of shader to compile as
1644         // (later these will all be bound together as a program object)
1645         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1646         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1647         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1648
1649         // the second pretext is the mode (for example a light source)
1650         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1651         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1652         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1653         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1654         strlcat(cachename, modeinfo->name, sizeof(cachename));
1655
1656         // now add all the permutation pretexts
1657         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1658         {
1659                 if (permutation & (1<<i))
1660                 {
1661                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1662                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1665                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1666                 }
1667                 else
1668                 {
1669                         // keep line numbers correct
1670                         vertstrings_list[vertstrings_count++] = "\n";
1671                         geomstrings_list[geomstrings_count++] = "\n";
1672                         fragstrings_list[fragstrings_count++] = "\n";
1673                 }
1674         }
1675
1676         // add static parms
1677         R_CompileShader_AddStaticParms(mode, permutation);
1678         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1679         vertstrings_count += shaderstaticparms_count;
1680         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         geomstrings_count += shaderstaticparms_count;
1682         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         fragstrings_count += shaderstaticparms_count;
1684
1685         // replace spaces in the cachename with _ characters
1686         for (i = 0;cachename[i];i++)
1687                 if (cachename[i] == ' ')
1688                         cachename[i] = '_';
1689
1690         // now append the shader text itself
1691         vertstrings_list[vertstrings_count++] = vertexstring;
1692         geomstrings_list[geomstrings_count++] = geometrystring;
1693         fragstrings_list[fragstrings_count++] = fragmentstring;
1694
1695         // if any sources were NULL, clear the respective list
1696         if (!vertexstring)
1697                 vertstrings_count = 0;
1698         if (!geometrystring)
1699                 geomstrings_count = 0;
1700         if (!fragmentstring)
1701                 fragstrings_count = 0;
1702
1703         vertstring_length = 0;
1704         for (i = 0;i < vertstrings_count;i++)
1705                 vertstring_length += strlen(vertstrings_list[i]);
1706         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1707         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1708                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1709
1710         geomstring_length = 0;
1711         for (i = 0;i < geomstrings_count;i++)
1712                 geomstring_length += strlen(geomstrings_list[i]);
1713         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1714         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1715                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1716
1717         fragstring_length = 0;
1718         for (i = 0;i < fragstrings_count;i++)
1719                 fragstring_length += strlen(fragstrings_list[i]);
1720         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1721         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1722                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1723
1724         // try to load the cached shader, or generate one
1725         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1726
1727         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1728                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1729         else
1730                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1731
1732         // free the strings
1733         if (vertstring)
1734                 Mem_Free(vertstring);
1735         if (geomstring)
1736                 Mem_Free(geomstring);
1737         if (fragstring)
1738                 Mem_Free(fragstring);
1739         if (vertexstring)
1740                 Mem_Free(vertexstring);
1741         if (geometrystring)
1742                 Mem_Free(geometrystring);
1743         if (fragmentstring)
1744                 Mem_Free(fragmentstring);
1745 }
1746
1747 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1748 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1749 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);}
1750 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);}
1751 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);}
1752 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);}
1753
1754 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 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);}
1757 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);}
1758 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);}
1759 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);}
1760
1761 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1762 {
1763         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1764         if (r_hlsl_permutation != perm)
1765         {
1766                 r_hlsl_permutation = perm;
1767                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1768                 {
1769                         if (!r_hlsl_permutation->compiled)
1770                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1771                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1772                         {
1773                                 // remove features until we find a valid permutation
1774                                 int i;
1775                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1776                                 {
1777                                         // reduce i more quickly whenever it would not remove any bits
1778                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1779                                         if (!(permutation & j))
1780                                                 continue;
1781                                         permutation -= j;
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         if (!r_hlsl_permutation->compiled)
1784                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1785                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1786                                                 break;
1787                                 }
1788                                 if (i >= SHADERPERMUTATION_COUNT)
1789                                 {
1790                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1791                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1792                                         return; // no bit left to clear, entire mode is broken
1793                                 }
1794                         }
1795                 }
1796                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1797                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1798         }
1799         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1800         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1801         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1802 }
1803 #endif
1804
1805 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1806 {
1807         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1808         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1809         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1810         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1811 }
1812
1813 void R_GLSL_Restart_f(void)
1814 {
1815         unsigned int i, limit;
1816         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1817                 Mem_Free(glslshaderstring);
1818         glslshaderstring = NULL;
1819         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1820                 Mem_Free(hlslshaderstring);
1821         hlslshaderstring = NULL;
1822         switch(vid.renderpath)
1823         {
1824         case RENDERPATH_D3D9:
1825 #ifdef SUPPORTD3D
1826                 {
1827                         r_hlsl_permutation_t *p;
1828                         r_hlsl_permutation = NULL;
1829                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1830                         for (i = 0;i < limit;i++)
1831                         {
1832                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1833                                 {
1834                                         if (p->vertexshader)
1835                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1836                                         if (p->pixelshader)
1837                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1838                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1842                 }
1843 #endif
1844                 break;
1845         case RENDERPATH_D3D10:
1846                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1847                 break;
1848         case RENDERPATH_D3D11:
1849                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850                 break;
1851         case RENDERPATH_GL20:
1852         case RENDERPATH_GLES2:
1853                 {
1854                         r_glsl_permutation_t *p;
1855                         r_glsl_permutation = NULL;
1856                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1857                         for (i = 0;i < limit;i++)
1858                         {
1859                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1860                                 {
1861                                         GL_Backend_FreeProgram(p->program);
1862                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1863                                 }
1864                         }
1865                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1866                 }
1867                 break;
1868         case RENDERPATH_GL11:
1869         case RENDERPATH_GL13:
1870         case RENDERPATH_GLES1:
1871                 break;
1872         case RENDERPATH_SOFT:
1873                 break;
1874         }
1875 }
1876
1877 void R_GLSL_DumpShader_f(void)
1878 {
1879         int i;
1880         qfile_t *file;
1881
1882         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1883         if (file)
1884         {
1885                 FS_Print(file, "/* The engine may define the following macros:\n");
1886                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887                 for (i = 0;i < SHADERMODE_COUNT;i++)
1888                         FS_Print(file, glslshadermodeinfo[i].pretext);
1889                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890                         FS_Print(file, shaderpermutationinfo[i].pretext);
1891                 FS_Print(file, "*/\n");
1892                 FS_Print(file, builtinshaderstring);
1893                 FS_Close(file);
1894                 Con_Printf("glsl/default.glsl written\n");
1895         }
1896         else
1897                 Con_Printf("failed to write to glsl/default.glsl\n");
1898
1899         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1900         if (file)
1901         {
1902                 FS_Print(file, "/* The engine may define the following macros:\n");
1903                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1904                 for (i = 0;i < SHADERMODE_COUNT;i++)
1905                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1906                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1907                         FS_Print(file, shaderpermutationinfo[i].pretext);
1908                 FS_Print(file, "*/\n");
1909                 FS_Print(file, builtinhlslshaderstring);
1910                 FS_Close(file);
1911                 Con_Printf("hlsl/default.hlsl written\n");
1912         }
1913         else
1914                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1915 }
1916
1917 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1918 {
1919         unsigned int permutation = 0;
1920         if (r_trippy.integer && !notrippy)
1921                 permutation |= SHADERPERMUTATION_TRIPPY;
1922         permutation |= SHADERPERMUTATION_VIEWTINT;
1923         if (first)
1924                 permutation |= SHADERPERMUTATION_DIFFUSE;
1925         if (second)
1926                 permutation |= SHADERPERMUTATION_SPECULAR;
1927         if (texturemode == GL_MODULATE)
1928                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1929         else if (texturemode == GL_ADD)
1930                 permutation |= SHADERPERMUTATION_GLOW;
1931         else if (texturemode == GL_DECAL)
1932                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1933         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1934                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1935         if (!second)
1936                 texturemode = GL_MODULATE;
1937         if (vid.allowalphatocoverage)
1938                 GL_AlphaToCoverage(false);
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTD3D
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1944                 R_Mesh_TexBind(GL20TU_FIRST , first );
1945                 R_Mesh_TexBind(GL20TU_SECOND, second);
1946                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1947                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1948 #endif
1949                 break;
1950         case RENDERPATH_D3D10:
1951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_D3D11:
1954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_GL20:
1957         case RENDERPATH_GLES2:
1958                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1959                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1960                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1961                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1962                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1963                 break;
1964         case RENDERPATH_GL13:
1965         case RENDERPATH_GLES1:
1966                 R_Mesh_TexBind(0, first );
1967                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1968                 R_Mesh_TexBind(1, second);
1969                 if (second)
1970                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1971                 break;
1972         case RENDERPATH_GL11:
1973                 R_Mesh_TexBind(0, first );
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1977                 R_Mesh_TexBind(GL20TU_FIRST , first );
1978                 R_Mesh_TexBind(GL20TU_SECOND, second);
1979                 break;
1980         }
1981 }
1982
1983 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1984 {
1985         unsigned int permutation = 0;
1986         if (r_trippy.integer && !notrippy)
1987                 permutation |= SHADERPERMUTATION_TRIPPY;
1988         if (vid.allowalphatocoverage)
1989                 GL_AlphaToCoverage(false);
1990         switch (vid.renderpath)
1991         {
1992         case RENDERPATH_D3D9:
1993 #ifdef SUPPORTD3D
1994                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         case RENDERPATH_GL13:
2008         case RENDERPATH_GLES1:
2009                 R_Mesh_TexBind(0, 0);
2010                 R_Mesh_TexBind(1, 0);
2011                 break;
2012         case RENDERPATH_GL11:
2013                 R_Mesh_TexBind(0, 0);
2014                 break;
2015         case RENDERPATH_SOFT:
2016                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         }
2019 }
2020
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 {
2023         int permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         if (vid.allowalphatocoverage)
2027                 GL_AlphaToCoverage(false);
2028         switch (vid.renderpath)
2029         {
2030         case RENDERPATH_D3D9:
2031 #ifdef SUPPORTHLSL
2032                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2033 #endif
2034                 break;
2035         case RENDERPATH_D3D10:
2036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037                 break;
2038         case RENDERPATH_D3D11:
2039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_GL20:
2042         case RENDERPATH_GLES2:
2043                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 break;
2048         case RENDERPATH_GL11:
2049                 break;
2050         case RENDERPATH_SOFT:
2051                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         }
2054 }
2055
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern cvar_t r_shadow_deferred_8bitrange;
2058 extern rtexture_t *r_shadow_attenuationgradienttexture;
2059 extern rtexture_t *r_shadow_attenuation2dtexture;
2060 extern rtexture_t *r_shadow_attenuation3dtexture;
2061 extern qboolean r_shadow_usingshadowmap2d;
2062 extern qboolean r_shadow_usingshadowmaportho;
2063 extern float r_shadow_shadowmap_texturescale[2];
2064 extern float r_shadow_shadowmap_parameters[4];
2065 extern qboolean r_shadow_shadowmapvsdct;
2066 extern qboolean r_shadow_shadowmapsampler;
2067 extern int r_shadow_shadowmappcf;
2068 extern rtexture_t *r_shadow_shadowmap2dtexture;
2069 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2070 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2071 extern matrix4x4_t r_shadow_shadowmapmatrix;
2072 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2073 extern int r_shadow_prepass_width;
2074 extern int r_shadow_prepass_height;
2075 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2076 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2078 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2079 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2080
2081 #define BLENDFUNC_ALLOWS_COLORMOD      1
2082 #define BLENDFUNC_ALLOWS_FOG           2
2083 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2084 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2085 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2086 static int R_BlendFuncFlags(int src, int dst)
2087 {
2088         int r = 0;
2089
2090         // a blendfunc allows colormod if:
2091         // a) it can never keep the destination pixel invariant, or
2092         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2093         // this is to prevent unintended side effects from colormod
2094
2095         // a blendfunc allows fog if:
2096         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2097         // this is to prevent unintended side effects from fog
2098
2099         // these checks are the output of fogeval.pl
2100
2101         r |= BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2111         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2115         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123
2124         return r;
2125 }
2126
2127 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)
2128 {
2129         // select a permutation of the lighting shader appropriate to this
2130         // combination of texture, entity, light source, and fogging, only use the
2131         // minimum features necessary to avoid wasting rendering time in the
2132         // fragment shader on features that are not being used
2133         unsigned int permutation = 0;
2134         unsigned int mode = 0;
2135         int blendfuncflags;
2136         static float dummy_colormod[3] = {1, 1, 1};
2137         float *colormod = rsurface.colormod;
2138         float m16f[16];
2139         matrix4x4_t tempmatrix;
2140         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2141         if (r_trippy.integer && !notrippy)
2142                 permutation |= SHADERPERMUTATION_TRIPPY;
2143         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2144                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2145         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2146                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2147         if (rsurfacepass == RSURFPASS_BACKGROUND)
2148         {
2149                 // distorted background
2150                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2151                 {
2152                         mode = SHADERMODE_WATER;
2153                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2154                         {
2155                                 // this is the right thing to do for wateralpha
2156                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2157                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2158                         }
2159                         else
2160                         {
2161                                 // this is the right thing to do for entity alpha
2162                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2164                         }
2165                 }
2166                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2167                 {
2168                         mode = SHADERMODE_REFRACTION;
2169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                 }
2172                 else
2173                 {
2174                         mode = SHADERMODE_GENERIC;
2175                         permutation |= SHADERPERMUTATION_DIFFUSE;
2176                         GL_BlendFunc(GL_ONE, GL_ZERO);
2177                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178                 }
2179                 if (vid.allowalphatocoverage)
2180                         GL_AlphaToCoverage(false);
2181         }
2182         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2183         {
2184                 if (r_glsl_offsetmapping.integer)
2185                 {
2186                         switch(rsurface.texture->offsetmapping)
2187                         {
2188                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191                         case OFFSETMAPPING_OFF: break;
2192                         }
2193                 }
2194                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196                 // normalmap (deferred prepass), may use alpha test on diffuse
2197                 mode = SHADERMODE_DEFERREDGEOMETRY;
2198                 GL_BlendFunc(GL_ONE, GL_ZERO);
2199                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200                 if (vid.allowalphatocoverage)
2201                         GL_AlphaToCoverage(false);
2202         }
2203         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2204         {
2205                 if (r_glsl_offsetmapping.integer)
2206                 {
2207                         switch(rsurface.texture->offsetmapping)
2208                         {
2209                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212                         case OFFSETMAPPING_OFF: break;
2213                         }
2214                 }
2215                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2217                 // light source
2218                 mode = SHADERMODE_LIGHTSOURCE;
2219                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2220                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2221                 if (diffusescale > 0)
2222                         permutation |= SHADERPERMUTATION_DIFFUSE;
2223                 if (specularscale > 0)
2224                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2225                 if (r_refdef.fogenabled)
2226                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2227                 if (rsurface.texture->colormapping)
2228                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2229                 if (r_shadow_usingshadowmap2d)
2230                 {
2231                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2232                         if(r_shadow_shadowmapvsdct)
2233                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2234
2235                         if (r_shadow_shadowmapsampler)
2236                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237                         if (r_shadow_shadowmappcf > 1)
2238                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239                         else if (r_shadow_shadowmappcf)
2240                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2241                 }
2242                 if (rsurface.texture->reflectmasktexture)
2243                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2244                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2245                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2246                 if (vid.allowalphatocoverage)
2247                         GL_AlphaToCoverage(false);
2248         }
2249         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2250         {
2251                 if (r_glsl_offsetmapping.integer)
2252                 {
2253                         switch(rsurface.texture->offsetmapping)
2254                         {
2255                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258                         case OFFSETMAPPING_OFF: break;
2259                         }
2260                 }
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263                 // unshaded geometry (fullbright or ambient model lighting)
2264                 mode = SHADERMODE_FLATCOLOR;
2265                 ambientscale = diffusescale = specularscale = 0;
2266                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267                         permutation |= SHADERPERMUTATION_GLOW;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmapsampler)
2278                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279                         if (r_shadow_shadowmappcf > 1)
2280                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281                         else if (r_shadow_shadowmappcf)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283                 }
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285                         permutation |= SHADERPERMUTATION_REFLECTION;
2286                 if (rsurface.texture->reflectmasktexture)
2287                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2288                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2290                 // when using alphatocoverage, we don't need alphakill
2291                 if (vid.allowalphatocoverage)
2292                 {
2293                         if (r_transparent_alphatocoverage.integer)
2294                         {
2295                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2296                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2297                         }
2298                         else
2299                                 GL_AlphaToCoverage(false);
2300                 }
2301         }
2302         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2303         {
2304                 if (r_glsl_offsetmapping.integer)
2305                 {
2306                         switch(rsurface.texture->offsetmapping)
2307                         {
2308                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2309                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2311                         case OFFSETMAPPING_OFF: break;
2312                         }
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316                 // directional model lighting
2317                 mode = SHADERMODE_LIGHTDIRECTION;
2318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319                         permutation |= SHADERPERMUTATION_GLOW;
2320                 permutation |= SHADERPERMUTATION_DIFFUSE;
2321                 if (specularscale > 0)
2322                         permutation |= SHADERPERMUTATION_SPECULAR;
2323                 if (r_refdef.fogenabled)
2324                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325                 if (rsurface.texture->colormapping)
2326                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2327                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2328                 {
2329                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2331
2332                         if (r_shadow_shadowmapsampler)
2333                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334                         if (r_shadow_shadowmappcf > 1)
2335                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336                         else if (r_shadow_shadowmappcf)
2337                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2338                 }
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340                         permutation |= SHADERPERMUTATION_REFLECTION;
2341                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343                 if (rsurface.texture->reflectmasktexture)
2344                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2346                 {
2347                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2348                         if (r_shadow_bouncegriddirectional)
2349                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2350                 }
2351                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353                 // when using alphatocoverage, we don't need alphakill
2354                 if (vid.allowalphatocoverage)
2355                 {
2356                         if (r_transparent_alphatocoverage.integer)
2357                         {
2358                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2360                         }
2361                         else
2362                                 GL_AlphaToCoverage(false);
2363                 }
2364         }
2365         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2366         {
2367                 if (r_glsl_offsetmapping.integer)
2368                 {
2369                         switch(rsurface.texture->offsetmapping)
2370                         {
2371                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374                         case OFFSETMAPPING_OFF: break;
2375                         }
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379                 // ambient model lighting
2380                 mode = SHADERMODE_LIGHTDIRECTION;
2381                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2382                         permutation |= SHADERPERMUTATION_GLOW;
2383                 if (r_refdef.fogenabled)
2384                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2385                 if (rsurface.texture->colormapping)
2386                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2387                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2388                 {
2389                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2390                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2391
2392                         if (r_shadow_shadowmapsampler)
2393                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2394                         if (r_shadow_shadowmappcf > 1)
2395                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2396                         else if (r_shadow_shadowmappcf)
2397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2400                         permutation |= SHADERPERMUTATION_REFLECTION;
2401                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2402                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2403                 if (rsurface.texture->reflectmasktexture)
2404                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2405                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2406                 {
2407                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2408                         if (r_shadow_bouncegriddirectional)
2409                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410                 }
2411                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 // when using alphatocoverage, we don't need alphakill
2414                 if (vid.allowalphatocoverage)
2415                 {
2416                         if (r_transparent_alphatocoverage.integer)
2417                         {
2418                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2419                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2420                         }
2421                         else
2422                                 GL_AlphaToCoverage(false);
2423                 }
2424         }
2425         else
2426         {
2427                 if (r_glsl_offsetmapping.integer)
2428                 {
2429                         switch(rsurface.texture->offsetmapping)
2430                         {
2431                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2432                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434                         case OFFSETMAPPING_OFF: break;
2435                         }
2436                 }
2437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2439                 // lightmapped wall
2440                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2441                         permutation |= SHADERPERMUTATION_GLOW;
2442                 if (r_refdef.fogenabled)
2443                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2444                 if (rsurface.texture->colormapping)
2445                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2446                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2447                 {
2448                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2449                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2450
2451                         if (r_shadow_shadowmapsampler)
2452                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2453                         if (r_shadow_shadowmappcf > 1)
2454                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2455                         else if (r_shadow_shadowmappcf)
2456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (FAKELIGHT_ENABLED)
2465                 {
2466                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467                         mode = SHADERMODE_FAKELIGHT;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473                 {
2474                         // deluxemapping (light direction texture)
2475                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (r_glsl_deluxemapping.integer >= 2)
2484                 {
2485                         // fake deluxemapping (uniform light direction in tangentspace)
2486                         if (rsurface.uselightmaptexture)
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488                         else
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490                         permutation |= SHADERPERMUTATION_DIFFUSE;
2491                         if (specularscale > 0)
2492                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493                 }
2494                 else if (rsurface.uselightmaptexture)
2495                 {
2496                         // ordinary lightmapping (q1bsp, q3bsp)
2497                         mode = SHADERMODE_LIGHTMAP;
2498                 }
2499                 else
2500                 {
2501                         // ordinary vertex coloring (q3bsp)
2502                         mode = SHADERMODE_VERTEXCOLOR;
2503                 }
2504                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505                 {
2506                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507                         if (r_shadow_bouncegriddirectional)
2508                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509                 }
2510                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 // when using alphatocoverage, we don't need alphakill
2513                 if (vid.allowalphatocoverage)
2514                 {
2515                         if (r_transparent_alphatocoverage.integer)
2516                         {
2517                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2519                         }
2520                         else
2521                                 GL_AlphaToCoverage(false);
2522                 }
2523         }
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525                 colormod = dummy_colormod;
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530         switch(vid.renderpath)
2531         {
2532         case RENDERPATH_D3D9:
2533 #ifdef SUPPORTD3D
2534                 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);
2535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_LIGHTDIRECTION)
2546                         {
2547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2548                         }
2549                 }
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555
2556                 if (mode == SHADERMODE_LIGHTSOURCE)
2557                 {
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563
2564                         // additive passes are only darkened by fog, not tinted
2565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2567                 }
2568                 else
2569                 {
2570                         if (mode == SHADERMODE_FLATCOLOR)
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573                         }
2574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2575                         {
2576                                 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]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578                                 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);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2583                         }
2584                         else
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588                                 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);
2589                                 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);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2591                         }
2592                         // additive passes are only darkened by fog, not tinted
2593                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595                         else
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597                         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);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                         if (mode == SHADERMODE_WATER)
2606                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607                 }
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611                 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));
2612                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613                 if (rsurface.texture->pantstexture)
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615                 else
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617                 if (rsurface.texture->shirttexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630                         );
2631                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2632                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2633                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2634
2635                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2636                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2637                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2638                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2643                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2645                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2647                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2648                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2649                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2650                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2651                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2652                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2653                 {
2654                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2655                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2656                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2657                 }
2658                 else
2659                 {
2660                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2661                 }
2662 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667                 {
2668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2669                         if (rsurface.rtlight)
2670                         {
2671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2673                         }
2674                 }
2675 #endif
2676                 break;
2677         case RENDERPATH_D3D10:
2678                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679                 break;
2680         case RENDERPATH_D3D11:
2681                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_GL20:
2684         case RENDERPATH_GLES2:
2685                 if (!vid.useinterleavedarrays)
2686                 {
2687                         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);
2688                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2695                 }
2696                 else
2697                 {
2698                         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);
2699                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700                 }
2701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703                 if (mode == SHADERMODE_LIGHTSOURCE)
2704                 {
2705                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710                         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);
2711         
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2716                 }
2717                 else
2718                 {
2719                         if (mode == SHADERMODE_FLATCOLOR)
2720                         {
2721                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722                         }
2723                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2724                         {
2725                                 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]);
2726                                 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]);
2727                                 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);
2728                                 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);
2729                                 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);
2730                                 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]);
2731                                 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]);
2732                         }
2733                         else
2734                         {
2735                                 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]);
2736                                 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]);
2737                                 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);
2738                                 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);
2739                                 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);
2740                         }
2741                         // additive passes are only darkened by fog, not tinted
2742                         if (r_glsl_permutation->loc_FogColor >= 0)
2743                         {
2744                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746                                 else
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         }
2749                         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);
2750                         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]);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2757                         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]);
2758                 }
2759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762                 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]);
2763                 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]);
2764
2765                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766                 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));
2767                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769                 {
2770                         if (rsurface.texture->pantstexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774                 }
2775                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776                 {
2777                         if (rsurface.texture->shirttexture)
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779                         else
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781                 }
2782                 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]);
2783                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791                         );
2792                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2793                 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]);
2794                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2795                 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);}
2796                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2797
2798                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2799                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2800                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2801                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2802                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2803                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2804                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2809                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2810                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2811                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2812                 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);
2813                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2814                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2815                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2816                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2817                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2818                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2819                 {
2820                         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);
2821                         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);
2822                         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);
2823                 }
2824                 else
2825                 {
2826                         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);
2827                 }
2828                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2829                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2830                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2831                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2832                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833                 {
2834                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2835                         if (rsurface.rtlight)
2836                         {
2837                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2838                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2839                         }
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2842                 CHECKGLERROR
2843                 break;
2844         case RENDERPATH_GL11:
2845         case RENDERPATH_GL13:
2846         case RENDERPATH_GLES1:
2847                 break;
2848         case RENDERPATH_SOFT:
2849                 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);
2850                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851                 R_SetupShader_SetPermutationSoft(mode, permutation);
2852                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853                 if (mode == SHADERMODE_LIGHTSOURCE)
2854                 {
2855                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861         
2862                         // additive passes are only darkened by fog, not tinted
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2865                 }
2866                 else
2867                 {
2868                         if (mode == SHADERMODE_FLATCOLOR)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871                         }
2872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2873                         {
2874                                 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]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876                                 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);
2877                                 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);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2879                                 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]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2881                         }
2882                         else
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886                                 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);
2887                                 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);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2889                         }
2890                         // additive passes are only darkened by fog, not tinted
2891                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895                         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);
2896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2898                         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]);
2899                         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]);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904                 }
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909                 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]);
2910
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912                 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));
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915                 {
2916                         if (rsurface.texture->pantstexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920                 }
2921                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922                 {
2923                         if (rsurface.texture->shirttexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927                 }
2928                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937                         );
2938                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2940
2941                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2942                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2943                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2944                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2945                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2946                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2949                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2950                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2951                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2952                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2953                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2954                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2955                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2956                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2957                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2958                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2959                 {
2960                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2961                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2962                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2963                 }
2964                 else
2965                 {
2966                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2969 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2970                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2971                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2972                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2973                 {
2974                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2975                         if (rsurface.rtlight)
2976                         {
2977                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2978                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2979                         }
2980                 }
2981                 break;
2982         }
2983 }
2984
2985 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2986 {
2987         // select a permutation of the lighting shader appropriate to this
2988         // combination of texture, entity, light source, and fogging, only use the
2989         // minimum features necessary to avoid wasting rendering time in the
2990         // fragment shader on features that are not being used
2991         unsigned int permutation = 0;
2992         unsigned int mode = 0;
2993         const float *lightcolorbase = rtlight->currentcolor;
2994         float ambientscale = rtlight->ambientscale;
2995         float diffusescale = rtlight->diffusescale;
2996         float specularscale = rtlight->specularscale;
2997         // this is the location of the light in view space
2998         vec3_t viewlightorigin;
2999         // this transforms from view space (camera) to light space (cubemap)
3000         matrix4x4_t viewtolight;
3001         matrix4x4_t lighttoview;
3002         float viewtolight16f[16];
3003         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3004         // light source
3005         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006         if (rtlight->currentcubemap != r_texture_whitecube)
3007                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008         if (diffusescale > 0)
3009                 permutation |= SHADERPERMUTATION_DIFFUSE;
3010         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012         if (r_shadow_usingshadowmap2d)
3013         {
3014                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015                 if (r_shadow_shadowmapvsdct)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017
3018                 if (r_shadow_shadowmapsampler)
3019                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3020                 if (r_shadow_shadowmappcf > 1)
3021                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3022                 else if (r_shadow_shadowmappcf)
3023                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3024         }
3025         if (vid.allowalphatocoverage)
3026                 GL_AlphaToCoverage(false);
3027         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3028         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3029         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3030         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3031         switch(vid.renderpath)
3032         {
3033         case RENDERPATH_D3D9:
3034 #ifdef SUPPORTD3D
3035                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3037                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3039                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3040                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3042                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3043                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, ((r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3044                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3045                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3046
3047                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3048                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3049                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3050                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3051                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3052                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3053 #endif
3054                 break;
3055         case RENDERPATH_D3D10:
3056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057                 break;
3058         case RENDERPATH_D3D11:
3059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3060                 break;
3061         case RENDERPATH_GL20:
3062         case RENDERPATH_GLES2:
3063                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3066                 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);
3067                 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);
3068                 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);
3069                 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]);
3070                 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]);
3071                 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) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3072                 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]);
3073                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3074
3075                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3076                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3077                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3078                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3079                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3080                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3081                 break;
3082         case RENDERPATH_GL11:
3083         case RENDERPATH_GL13:
3084         case RENDERPATH_GLES1:
3085                 break;
3086         case RENDERPATH_SOFT:
3087                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3089                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3090                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3091                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3092                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3093                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3094                 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]);
3095                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , ((r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3096                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3097                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3098
3099                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3100                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3101                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3102                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3103                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3104                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3105                 break;
3106         }
3107 }
3108
3109 #define SKINFRAME_HASH 1024
3110
3111 typedef struct
3112 {
3113         int loadsequence; // incremented each level change
3114         memexpandablearray_t array;
3115         skinframe_t *hash[SKINFRAME_HASH];
3116 }
3117 r_skinframe_t;
3118 r_skinframe_t r_skinframe;
3119
3120 void R_SkinFrame_PrepareForPurge(void)
3121 {
3122         r_skinframe.loadsequence++;
3123         // wrap it without hitting zero
3124         if (r_skinframe.loadsequence >= 200)
3125                 r_skinframe.loadsequence = 1;
3126 }
3127
3128 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3129 {
3130         if (!skinframe)
3131                 return;
3132         // mark the skinframe as used for the purging code
3133         skinframe->loadsequence = r_skinframe.loadsequence;
3134 }
3135
3136 void R_SkinFrame_Purge(void)
3137 {
3138         int i;
3139         skinframe_t *s;
3140         for (i = 0;i < SKINFRAME_HASH;i++)
3141         {
3142                 for (s = r_skinframe.hash[i];s;s = s->next)
3143                 {
3144                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3145                         {
3146                                 if (s->merged == s->base)
3147                                         s->merged = NULL;
3148                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3149                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3150                                 R_PurgeTexture(s->merged);s->merged = NULL;
3151                                 R_PurgeTexture(s->base  );s->base   = NULL;
3152                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3153                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3154                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3155                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3156                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3157                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3158                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3159                                 s->loadsequence = 0;
3160                         }
3161                 }
3162         }
3163 }
3164
3165 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3166         skinframe_t *item;
3167         char basename[MAX_QPATH];
3168
3169         Image_StripImageExtension(name, basename, sizeof(basename));
3170
3171         if( last == NULL ) {
3172                 int hashindex;
3173                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3174                 item = r_skinframe.hash[hashindex];
3175         } else {
3176                 item = last->next;
3177         }
3178
3179         // linearly search through the hash bucket
3180         for( ; item ; item = item->next ) {
3181                 if( !strcmp( item->basename, basename ) ) {
3182                         return item;
3183                 }
3184         }
3185         return NULL;
3186 }
3187
3188 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3189 {
3190         skinframe_t *item;
3191         int hashindex;
3192         char basename[MAX_QPATH];
3193
3194         Image_StripImageExtension(name, basename, sizeof(basename));
3195
3196         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3197         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3198                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3199                         break;
3200
3201         if (!item) {
3202                 rtexture_t *dyntexture;
3203                 // check whether its a dynamic texture
3204                 dyntexture = CL_GetDynTexture( basename );
3205                 if (!add && !dyntexture)
3206                         return NULL;
3207                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3208                 memset(item, 0, sizeof(*item));
3209                 strlcpy(item->basename, basename, sizeof(item->basename));
3210                 item->base = dyntexture; // either NULL or dyntexture handle
3211                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3212                 item->comparewidth = comparewidth;
3213                 item->compareheight = compareheight;
3214                 item->comparecrc = comparecrc;
3215                 item->next = r_skinframe.hash[hashindex];
3216                 r_skinframe.hash[hashindex] = item;
3217         }
3218         else if (textureflags & TEXF_FORCE_RELOAD)
3219         {
3220                 rtexture_t *dyntexture;
3221                 // check whether its a dynamic texture
3222                 dyntexture = CL_GetDynTexture( basename );
3223                 if (!add && !dyntexture)
3224                         return NULL;
3225                 if (item->merged == item->base)
3226                         item->merged = NULL;
3227                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3228                 R_PurgeTexture(item->stain );item->stain  = NULL;
3229                 R_PurgeTexture(item->merged);item->merged = NULL;
3230                 R_PurgeTexture(item->base  );item->base   = NULL;
3231                 R_PurgeTexture(item->pants );item->pants  = NULL;
3232                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3233                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3234                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3235                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3236                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3237         R_PurgeTexture(item->reflect);item->reflect = NULL;
3238                 item->loadsequence = 0;
3239         }
3240         else if( item->base == NULL )
3241         {
3242                 rtexture_t *dyntexture;
3243                 // check whether its a dynamic texture
3244                 // 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]
3245                 dyntexture = CL_GetDynTexture( basename );
3246                 item->base = dyntexture; // either NULL or dyntexture handle
3247         }
3248
3249         R_SkinFrame_MarkUsed(item);
3250         return item;
3251 }
3252
3253 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3254         { \
3255                 unsigned long long avgcolor[5], wsum; \
3256                 int pix, comp, w; \
3257                 avgcolor[0] = 0; \
3258                 avgcolor[1] = 0; \
3259                 avgcolor[2] = 0; \
3260                 avgcolor[3] = 0; \
3261                 avgcolor[4] = 0; \
3262                 wsum = 0; \
3263                 for(pix = 0; pix < cnt; ++pix) \
3264                 { \
3265                         w = 0; \
3266                         for(comp = 0; comp < 3; ++comp) \
3267                                 w += getpixel; \
3268                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3269                         { \
3270                                 ++wsum; \
3271                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3272                                 w = getpixel; \
3273                                 for(comp = 0; comp < 3; ++comp) \
3274                                         avgcolor[comp] += getpixel * w; \
3275                                 avgcolor[3] += w; \
3276                         } \
3277                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3278                         avgcolor[4] += getpixel; \
3279                 } \
3280                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3281                         avgcolor[3] = 1; \
3282                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3283                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3284                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3285                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3286         }
3287
3288 extern cvar_t gl_picmip;
3289 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3290 {
3291         int j;
3292         unsigned char *pixels;
3293         unsigned char *bumppixels;
3294         unsigned char *basepixels = NULL;
3295         int basepixels_width = 0;
3296         int basepixels_height = 0;
3297         skinframe_t *skinframe;
3298         rtexture_t *ddsbase = NULL;
3299         qboolean ddshasalpha = false;
3300         float ddsavgcolor[4];
3301         char basename[MAX_QPATH];
3302         int miplevel = R_PicmipForFlags(textureflags);
3303         int savemiplevel = miplevel;
3304         int mymiplevel;
3305
3306         if (cls.state == ca_dedicated)
3307                 return NULL;
3308
3309         // return an existing skinframe if already loaded
3310         // if loading of the first image fails, don't make a new skinframe as it
3311         // would cause all future lookups of this to be missing
3312         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3313         if (skinframe && skinframe->base)
3314                 return skinframe;
3315
3316         Image_StripImageExtension(name, basename, sizeof(basename));
3317
3318         // check for DDS texture file first
3319         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3320         {
3321                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3322                 if (basepixels == NULL)
3323                         return NULL;
3324         }
3325
3326         // FIXME handle miplevel
3327
3328         if (developer_loading.integer)
3329                 Con_Printf("loading skin \"%s\"\n", name);
3330
3331         // we've got some pixels to store, so really allocate this new texture now
3332         if (!skinframe)
3333                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3334         textureflags &= ~TEXF_FORCE_RELOAD;
3335         skinframe->stain = NULL;
3336         skinframe->merged = NULL;
3337         skinframe->base = NULL;
3338         skinframe->pants = NULL;
3339         skinframe->shirt = NULL;
3340         skinframe->nmap = NULL;
3341         skinframe->gloss = NULL;
3342         skinframe->glow = NULL;
3343         skinframe->fog = NULL;
3344         skinframe->reflect = NULL;
3345         skinframe->hasalpha = false;
3346
3347         if (ddsbase)
3348         {
3349                 skinframe->base = ddsbase;
3350                 skinframe->hasalpha = ddshasalpha;
3351                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3352                 if (r_loadfog && skinframe->hasalpha)
3353                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3354                 //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]);
3355         }
3356         else
3357         {
3358                 basepixels_width = image_width;
3359                 basepixels_height = image_height;
3360                 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);
3361                 if (textureflags & TEXF_ALPHA)
3362                 {
3363                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3364                         {
3365                                 if (basepixels[j] < 255)
3366                                 {
3367                                         skinframe->hasalpha = true;
3368                                         break;
3369                                 }
3370                         }
3371                         if (r_loadfog && skinframe->hasalpha)
3372                         {
3373                                 // has transparent pixels
3374                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3375                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3376                                 {
3377                                         pixels[j+0] = 255;
3378                                         pixels[j+1] = 255;
3379                                         pixels[j+2] = 255;
3380                                         pixels[j+3] = basepixels[j+3];
3381                                 }
3382                                 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);
3383                                 Mem_Free(pixels);
3384                         }
3385                 }
3386                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3387 #ifndef USE_GLES2
3388                 //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]);
3389                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3390                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3391                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3392                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3393 #endif
3394         }
3395
3396         if (r_loaddds)
3397         {
3398                 mymiplevel = savemiplevel;
3399                 if (r_loadnormalmap)
3400                         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);
3401                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3402                 if (r_loadgloss)
3403                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3404                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3405                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3406                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3407         }
3408
3409         // _norm is the name used by tenebrae and has been adopted as standard
3410         if (r_loadnormalmap && skinframe->nmap == NULL)
3411         {
3412                 mymiplevel = savemiplevel;
3413                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3414                 {
3415                         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);
3416                         Mem_Free(pixels);
3417                         pixels = NULL;
3418                 }
3419                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3420                 {
3421                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3422                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
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                         Mem_Free(bumppixels);
3426                 }
3427                 else if (r_shadow_bumpscale_basetexture.value > 0)
3428                 {
3429                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3430                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3431                         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);
3432                         Mem_Free(pixels);
3433                 }
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3436                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438         }
3439
3440         // _luma is supported only for tenebrae compatibility
3441         // _glow is the preferred name
3442         mymiplevel = savemiplevel;
3443         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))))
3444         {
3445                 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);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3448                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3449 #endif
3450                 Mem_Free(pixels);pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3459                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         mymiplevel = savemiplevel;
3466         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3467         {
3468                 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);
3469 #ifndef USE_GLES2
3470                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3471                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3472 #endif
3473                 Mem_Free(pixels);
3474                 pixels = NULL;
3475         }
3476
3477         mymiplevel = savemiplevel;
3478         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3479         {
3480                 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);
3481 #ifndef USE_GLES2
3482                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3483                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3484 #endif
3485                 Mem_Free(pixels);
3486                 pixels = NULL;
3487         }
3488
3489         mymiplevel = savemiplevel;
3490         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3491         {
3492                 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);
3493 #ifndef USE_GLES2
3494                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3495                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3496 #endif
3497                 Mem_Free(pixels);
3498                 pixels = NULL;
3499         }
3500
3501         if (basepixels)
3502                 Mem_Free(basepixels);
3503
3504         return skinframe;
3505 }
3506
3507 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3508 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3509 {
3510         int i;
3511         unsigned char *temp1, *temp2;
3512         skinframe_t *skinframe;
3513
3514         if (cls.state == ca_dedicated)
3515                 return NULL;
3516
3517         // if already loaded just return it, otherwise make a new skinframe
3518         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3519         if (skinframe && skinframe->base)
3520                 return skinframe;
3521         textureflags &= ~TEXF_FORCE_RELOAD;
3522
3523         skinframe->stain = NULL;
3524         skinframe->merged = NULL;
3525         skinframe->base = NULL;
3526         skinframe->pants = NULL;
3527         skinframe->shirt = NULL;
3528         skinframe->nmap = NULL;
3529         skinframe->gloss = NULL;
3530         skinframe->glow = NULL;
3531         skinframe->fog = NULL;
3532         skinframe->reflect = NULL;
3533         skinframe->hasalpha = false;
3534
3535         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3536         if (!skindata)
3537                 return NULL;
3538
3539         if (developer_loading.integer)
3540                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3541
3542         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3543         {
3544                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3545                 temp2 = temp1 + width * height * 4;
3546                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3547                 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);
3548                 Mem_Free(temp1);
3549         }
3550         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3551         if (textureflags & TEXF_ALPHA)
3552         {
3553                 for (i = 3;i < width * height * 4;i += 4)
3554                 {
3555                         if (skindata[i] < 255)
3556                         {
3557                                 skinframe->hasalpha = true;
3558                                 break;
3559                         }
3560                 }
3561                 if (r_loadfog && skinframe->hasalpha)
3562                 {
3563                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3564                         memcpy(fogpixels, skindata, width * height * 4);
3565                         for (i = 0;i < width * height * 4;i += 4)
3566                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3567                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3568                         Mem_Free(fogpixels);
3569                 }
3570         }
3571
3572         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3573         //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]);
3574
3575         return skinframe;
3576 }
3577
3578 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3579 {
3580         int i;
3581         int featuresmask;
3582         skinframe_t *skinframe;
3583
3584         if (cls.state == ca_dedicated)
3585                 return NULL;
3586
3587         // if already loaded just return it, otherwise make a new skinframe
3588         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3589         if (skinframe && skinframe->base)
3590                 return skinframe;
3591         textureflags &= ~TEXF_FORCE_RELOAD;
3592
3593         skinframe->stain = NULL;
3594         skinframe->merged = NULL;
3595         skinframe->base = NULL;
3596         skinframe->pants = NULL;
3597         skinframe->shirt = NULL;
3598         skinframe->nmap = NULL;
3599         skinframe->gloss = NULL;
3600         skinframe->glow = NULL;
3601         skinframe->fog = NULL;
3602         skinframe->reflect = NULL;
3603         skinframe->hasalpha = false;
3604
3605         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3606         if (!skindata)
3607                 return NULL;
3608
3609         if (developer_loading.integer)
3610                 Con_Printf("loading quake skin \"%s\"\n", name);
3611
3612         // 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)
3613         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3614         memcpy(skinframe->qpixels, skindata, width*height);
3615         skinframe->qwidth = width;
3616         skinframe->qheight = height;
3617
3618         featuresmask = 0;
3619         for (i = 0;i < width * height;i++)
3620                 featuresmask |= palette_featureflags[skindata[i]];
3621
3622         skinframe->hasalpha = false;
3623         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3624         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3625         skinframe->qgeneratemerged = true;
3626         skinframe->qgeneratebase = skinframe->qhascolormapping;
3627         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3628
3629         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3630         //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]);
3631
3632         return skinframe;
3633 }
3634
3635 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3636 {
3637         int width;
3638         int height;
3639         unsigned char *skindata;
3640
3641         if (!skinframe->qpixels)
3642                 return;
3643
3644         if (!skinframe->qhascolormapping)
3645                 colormapped = false;
3646
3647         if (colormapped)
3648         {
3649                 if (!skinframe->qgeneratebase)
3650                         return;
3651         }
3652         else
3653         {
3654                 if (!skinframe->qgeneratemerged)
3655                         return;
3656         }
3657
3658         width = skinframe->qwidth;
3659         height = skinframe->qheight;
3660         skindata = skinframe->qpixels;
3661
3662         if (skinframe->qgeneratenmap)
3663         {
3664                 unsigned char *temp1, *temp2;
3665                 skinframe->qgeneratenmap = false;
3666                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3667                 temp2 = temp1 + width * height * 4;
3668                 // use either a custom palette or the quake palette
3669                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3670                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3671                 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);
3672                 Mem_Free(temp1);
3673         }
3674
3675         if (skinframe->qgenerateglow)
3676         {
3677                 skinframe->qgenerateglow = false;
3678                 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
3679         }
3680
3681         if (colormapped)
3682         {
3683                 skinframe->qgeneratebase = false;
3684                 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);
3685                 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);
3686                 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);
3687         }
3688         else
3689         {
3690                 skinframe->qgeneratemerged = false;
3691                 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);
3692         }
3693
3694         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3695         {
3696                 Mem_Free(skinframe->qpixels);
3697                 skinframe->qpixels = NULL;
3698         }
3699 }
3700
3701 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)
3702 {
3703         int i;
3704         skinframe_t *skinframe;
3705
3706         if (cls.state == ca_dedicated)
3707                 return NULL;
3708
3709         // if already loaded just return it, otherwise make a new skinframe
3710         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3711         if (skinframe && skinframe->base)
3712                 return skinframe;
3713         textureflags &= ~TEXF_FORCE_RELOAD;
3714
3715         skinframe->stain = NULL;
3716         skinframe->merged = NULL;
3717         skinframe->base = NULL;
3718         skinframe->pants = NULL;
3719         skinframe->shirt = NULL;
3720         skinframe->nmap = NULL;
3721         skinframe->gloss = NULL;
3722         skinframe->glow = NULL;
3723         skinframe->fog = NULL;
3724         skinframe->reflect = NULL;
3725         skinframe->hasalpha = false;
3726
3727         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3728         if (!skindata)
3729                 return NULL;
3730
3731         if (developer_loading.integer)
3732                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3733
3734         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3735         if (textureflags & TEXF_ALPHA)
3736         {
3737                 for (i = 0;i < width * height;i++)
3738                 {
3739                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3740                         {
3741                                 skinframe->hasalpha = true;
3742                                 break;
3743                         }
3744                 }
3745                 if (r_loadfog && skinframe->hasalpha)
3746                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3747         }
3748
3749         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3750         //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]);
3751
3752         return skinframe;
3753 }
3754
3755 skinframe_t *R_SkinFrame_LoadMissing(void)
3756 {
3757         skinframe_t *skinframe;
3758
3759         if (cls.state == ca_dedicated)
3760                 return NULL;
3761
3762         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3763         skinframe->stain = NULL;
3764         skinframe->merged = NULL;
3765         skinframe->base = NULL;
3766         skinframe->pants = NULL;
3767         skinframe->shirt = NULL;
3768         skinframe->nmap = NULL;
3769         skinframe->gloss = NULL;
3770         skinframe->glow = NULL;
3771         skinframe->fog = NULL;
3772         skinframe->reflect = NULL;
3773         skinframe->hasalpha = false;
3774
3775         skinframe->avgcolor[0] = rand() / RAND_MAX;
3776         skinframe->avgcolor[1] = rand() / RAND_MAX;
3777         skinframe->avgcolor[2] = rand() / RAND_MAX;
3778         skinframe->avgcolor[3] = 1;
3779
3780         return skinframe;
3781 }
3782
3783 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3784 typedef struct suffixinfo_s
3785 {
3786         const char *suffix;
3787         qboolean flipx, flipy, flipdiagonal;
3788 }
3789 suffixinfo_t;
3790 static suffixinfo_t suffix[3][6] =
3791 {
3792         {
3793                 {"px",   false, false, false},
3794                 {"nx",   false, false, false},
3795                 {"py",   false, false, false},
3796                 {"ny",   false, false, false},
3797                 {"pz",   false, false, false},
3798                 {"nz",   false, false, false}
3799         },
3800         {
3801                 {"posx", false, false, false},
3802                 {"negx", false, false, false},
3803                 {"posy", false, false, false},
3804                 {"negy", false, false, false},
3805                 {"posz", false, false, false},
3806                 {"negz", false, false, false}
3807         },
3808         {
3809                 {"rt",    true, false,  true},
3810                 {"lf",   false,  true,  true},
3811                 {"ft",    true,  true, false},
3812                 {"bk",   false, false, false},
3813                 {"up",    true, false,  true},
3814                 {"dn",    true, false,  true}
3815         }
3816 };
3817
3818 static int componentorder[4] = {0, 1, 2, 3};
3819
3820 rtexture_t *R_LoadCubemap(const char *basename)
3821 {
3822         int i, j, cubemapsize;
3823         unsigned char *cubemappixels, *image_buffer;
3824         rtexture_t *cubemaptexture;
3825         char name[256];
3826         // must start 0 so the first loadimagepixels has no requested width/height
3827         cubemapsize = 0;
3828         cubemappixels = NULL;
3829         cubemaptexture = NULL;
3830         // keep trying different suffix groups (posx, px, rt) until one loads
3831         for (j = 0;j < 3 && !cubemappixels;j++)
3832         {
3833                 // load the 6 images in the suffix group
3834                 for (i = 0;i < 6;i++)
3835                 {
3836                         // generate an image name based on the base and and suffix
3837                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3838                         // load it
3839                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3840                         {
3841                                 // an image loaded, make sure width and height are equal
3842                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3843                                 {
3844                                         // if this is the first image to load successfully, allocate the cubemap memory
3845                                         if (!cubemappixels && image_width >= 1)
3846                                         {
3847                                                 cubemapsize = image_width;
3848                                                 // note this clears to black, so unavailable sides are black
3849                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3850                                         }
3851                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3852                                         if (cubemappixels)
3853                                                 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);
3854                                 }
3855                                 else
3856                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3857                                 // free the image
3858                                 Mem_Free(image_buffer);
3859                         }
3860                 }
3861         }
3862         // if a cubemap loaded, upload it
3863         if (cubemappixels)
3864         {
3865                 if (developer_loading.integer)
3866                         Con_Printf("loading cubemap \"%s\"\n", basename);
3867
3868                 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);
3869                 Mem_Free(cubemappixels);
3870         }
3871         else
3872         {
3873                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3874                 if (developer_loading.integer)
3875                 {
3876                         Con_Printf("(tried tried images ");
3877                         for (j = 0;j < 3;j++)
3878                                 for (i = 0;i < 6;i++)
3879                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3880                         Con_Print(" and was unable to find any of them).\n");
3881                 }
3882         }
3883         return cubemaptexture;
3884 }
3885
3886 rtexture_t *R_GetCubemap(const char *basename)
3887 {
3888         int i;
3889         for (i = 0;i < r_texture_numcubemaps;i++)
3890                 if (r_texture_cubemaps[i] != NULL)
3891                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3892                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3893         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3894                 return r_texture_whitecube;
3895         r_texture_numcubemaps++;
3896         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3897         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3898         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3899         return r_texture_cubemaps[i]->texture;
3900 }
3901
3902 void R_FreeCubemap(const char *basename)
3903 {
3904         int i;
3905
3906         for (i = 0;i < r_texture_numcubemaps;i++)
3907         {
3908                 if (r_texture_cubemaps[i] != NULL)
3909                 {
3910                         if (r_texture_cubemaps[i]->texture)
3911                         {
3912                                 if (developer_loading.integer)
3913                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3914                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3915                                 Mem_Free(r_texture_cubemaps[i]);
3916                                 r_texture_cubemaps[i] = NULL;
3917                         }
3918                 }
3919         }
3920 }
3921
3922 void R_FreeCubemaps(void)
3923 {
3924         int i;
3925         for (i = 0;i < r_texture_numcubemaps;i++)
3926         {
3927                 if (developer_loading.integer)
3928                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3929                 if (r_texture_cubemaps[i] != NULL)
3930                 {
3931                         if (r_texture_cubemaps[i]->texture)
3932                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3933                         Mem_Free(r_texture_cubemaps[i]);
3934                 }
3935         }
3936         r_texture_numcubemaps = 0;
3937 }
3938
3939 void R_Main_FreeViewCache(void)
3940 {
3941         if (r_refdef.viewcache.entityvisible)
3942                 Mem_Free(r_refdef.viewcache.entityvisible);
3943         if (r_refdef.viewcache.world_pvsbits)
3944                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3945         if (r_refdef.viewcache.world_leafvisible)
3946                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3947         if (r_refdef.viewcache.world_surfacevisible)
3948                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3949         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3950 }
3951
3952 void R_Main_ResizeViewCache(void)
3953 {
3954         int numentities = r_refdef.scene.numentities;
3955         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3956         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3957         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3958         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3959         if (r_refdef.viewcache.maxentities < numentities)
3960         {
3961                 r_refdef.viewcache.maxentities = numentities;
3962                 if (r_refdef.viewcache.entityvisible)
3963                         Mem_Free(r_refdef.viewcache.entityvisible);
3964                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3965         }
3966         if (r_refdef.viewcache.world_numclusters != numclusters)
3967         {
3968                 r_refdef.viewcache.world_numclusters = numclusters;
3969                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3970                 if (r_refdef.viewcache.world_pvsbits)
3971                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3972                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3973         }
3974         if (r_refdef.viewcache.world_numleafs != numleafs)
3975         {
3976                 r_refdef.viewcache.world_numleafs = numleafs;
3977                 if (r_refdef.viewcache.world_leafvisible)
3978                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3979                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3980         }
3981         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3982         {
3983                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3984                 if (r_refdef.viewcache.world_surfacevisible)
3985                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3986                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3987         }
3988 }
3989
3990 extern rtexture_t *loadingscreentexture;
3991 void gl_main_start(void)
3992 {
3993         loadingscreentexture = NULL;
3994         r_texture_blanknormalmap = NULL;
3995         r_texture_white = NULL;
3996         r_texture_grey128 = NULL;
3997         r_texture_black = NULL;
3998         r_texture_whitecube = NULL;
3999         r_texture_normalizationcube = NULL;
4000         r_texture_fogattenuation = NULL;
4001         r_texture_fogheighttexture = NULL;
4002         r_texture_gammaramps = NULL;
4003         r_texture_numcubemaps = 0;
4004
4005         r_loaddds = r_texture_dds_load.integer != 0;
4006         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4007
4008         switch(vid.renderpath)
4009         {
4010         case RENDERPATH_GL20:
4011         case RENDERPATH_D3D9:
4012         case RENDERPATH_D3D10:
4013         case RENDERPATH_D3D11:
4014         case RENDERPATH_SOFT:
4015         case RENDERPATH_GLES2:
4016                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4017                 Cvar_SetValueQuick(&gl_combine, 1);
4018                 Cvar_SetValueQuick(&r_glsl, 1);
4019                 r_loadnormalmap = true;
4020                 r_loadgloss = true;
4021                 r_loadfog = false;
4022                 break;
4023         case RENDERPATH_GL13:
4024         case RENDERPATH_GLES1:
4025                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4026                 Cvar_SetValueQuick(&gl_combine, 1);
4027                 Cvar_SetValueQuick(&r_glsl, 0);
4028                 r_loadnormalmap = false;
4029                 r_loadgloss = false;
4030                 r_loadfog = true;
4031                 break;
4032         case RENDERPATH_GL11:
4033                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4034                 Cvar_SetValueQuick(&gl_combine, 0);
4035                 Cvar_SetValueQuick(&r_glsl, 0);
4036                 r_loadnormalmap = false;
4037                 r_loadgloss = false;
4038                 r_loadfog = true;
4039                 break;
4040         }
4041
4042         R_AnimCache_Free();
4043         R_FrameData_Reset();
4044
4045         r_numqueries = 0;
4046         r_maxqueries = 0;
4047         memset(r_queries, 0, sizeof(r_queries));
4048
4049         r_qwskincache = NULL;
4050         r_qwskincache_size = 0;
4051
4052         // due to caching of texture_t references, the collision cache must be reset
4053         Collision_Cache_Reset(true);
4054
4055         // set up r_skinframe loading system for textures
4056         memset(&r_skinframe, 0, sizeof(r_skinframe));
4057         r_skinframe.loadsequence = 1;
4058         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4059
4060         r_main_texturepool = R_AllocTexturePool();
4061         R_BuildBlankTextures();
4062         R_BuildNoTexture();
4063         if (vid.support.arb_texture_cube_map)
4064         {
4065                 R_BuildWhiteCube();
4066                 R_BuildNormalizationCube();
4067         }
4068         r_texture_fogattenuation = NULL;
4069         r_texture_fogheighttexture = NULL;
4070         r_texture_gammaramps = NULL;
4071         //r_texture_fogintensity = NULL;
4072         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4073         memset(&r_waterstate, 0, sizeof(r_waterstate));
4074         r_glsl_permutation = NULL;
4075         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4076         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4077         glslshaderstring = NULL;
4078 #ifdef SUPPORTD3D
4079         r_hlsl_permutation = NULL;
4080         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4081         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4082 #endif
4083         hlslshaderstring = NULL;
4084         memset(&r_svbsp, 0, sizeof (r_svbsp));
4085
4086         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4087         r_texture_numcubemaps = 0;
4088
4089         r_refdef.fogmasktable_density = 0;
4090 }
4091
4092 void gl_main_shutdown(void)
4093 {
4094         R_AnimCache_Free();
4095         R_FrameData_Reset();
4096
4097         R_Main_FreeViewCache();
4098
4099         switch(vid.renderpath)
4100         {
4101         case RENDERPATH_GL11:
4102         case RENDERPATH_GL13:
4103         case RENDERPATH_GL20:
4104         case RENDERPATH_GLES1:
4105         case RENDERPATH_GLES2:
4106 #ifdef GL_SAMPLES_PASSED_ARB
4107                 if (r_maxqueries)
4108                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4109 #endif
4110                 break;
4111         case RENDERPATH_D3D9:
4112                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4113                 break;
4114         case RENDERPATH_D3D10:
4115                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4116                 break;
4117         case RENDERPATH_D3D11:
4118                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4119                 break;
4120         case RENDERPATH_SOFT:
4121                 break;
4122         }
4123
4124         r_numqueries = 0;
4125         r_maxqueries = 0;
4126         memset(r_queries, 0, sizeof(r_queries));
4127
4128         r_qwskincache = NULL;
4129         r_qwskincache_size = 0;
4130
4131         // clear out the r_skinframe state
4132         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4133         memset(&r_skinframe, 0, sizeof(r_skinframe));
4134
4135         if (r_svbsp.nodes)
4136                 Mem_Free(r_svbsp.nodes);
4137         memset(&r_svbsp, 0, sizeof (r_svbsp));
4138         R_FreeTexturePool(&r_main_texturepool);
4139         loadingscreentexture = NULL;
4140         r_texture_blanknormalmap = NULL;
4141         r_texture_white = NULL;
4142         r_texture_grey128 = NULL;
4143         r_texture_black = NULL;
4144         r_texture_whitecube = NULL;
4145         r_texture_normalizationcube = NULL;
4146         r_texture_fogattenuation = NULL;
4147         r_texture_fogheighttexture = NULL;
4148         r_texture_gammaramps = NULL;
4149         r_texture_numcubemaps = 0;
4150         //r_texture_fogintensity = NULL;
4151         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4152         memset(&r_waterstate, 0, sizeof(r_waterstate));
4153         R_GLSL_Restart_f();
4154
4155         r_glsl_permutation = NULL;
4156         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4157         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4158         glslshaderstring = NULL;
4159 #ifdef SUPPORTD3D
4160         r_hlsl_permutation = NULL;
4161         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4162         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4163 #endif
4164         hlslshaderstring = NULL;
4165 }
4166
4167 extern void CL_ParseEntityLump(char *entitystring);
4168 void gl_main_newmap(void)
4169 {
4170         // FIXME: move this code to client
4171         char *entities, entname[MAX_QPATH];
4172         if (r_qwskincache)
4173                 Mem_Free(r_qwskincache);
4174         r_qwskincache = NULL;
4175         r_qwskincache_size = 0;
4176         if (cl.worldmodel)
4177         {
4178                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4179                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4180                 {
4181                         CL_ParseEntityLump(entities);
4182                         Mem_Free(entities);
4183                         return;
4184                 }
4185                 if (cl.worldmodel->brush.entities)
4186                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4187         }
4188         R_Main_FreeViewCache();
4189
4190         R_FrameData_Reset();
4191 }
4192
4193 void GL_Main_Init(void)
4194 {
4195         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4196
4197         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4198         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4199         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4200         if (gamemode == GAME_NEHAHRA)
4201         {
4202                 Cvar_RegisterVariable (&gl_fogenable);
4203                 Cvar_RegisterVariable (&gl_fogdensity);
4204                 Cvar_RegisterVariable (&gl_fogred);
4205                 Cvar_RegisterVariable (&gl_foggreen);
4206                 Cvar_RegisterVariable (&gl_fogblue);
4207                 Cvar_RegisterVariable (&gl_fogstart);
4208                 Cvar_RegisterVariable (&gl_fogend);
4209                 Cvar_RegisterVariable (&gl_skyclip);
4210         }
4211         Cvar_RegisterVariable(&r_motionblur);
4212         Cvar_RegisterVariable(&r_damageblur);
4213         Cvar_RegisterVariable(&r_motionblur_averaging);
4214         Cvar_RegisterVariable(&r_motionblur_randomize);
4215         Cvar_RegisterVariable(&r_motionblur_minblur);
4216         Cvar_RegisterVariable(&r_motionblur_maxblur);
4217         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4218         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4219         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4220         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4221         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4222         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4223         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4224         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4225         Cvar_RegisterVariable(&r_equalize_entities_by);
4226         Cvar_RegisterVariable(&r_equalize_entities_to);
4227         Cvar_RegisterVariable(&r_depthfirst);
4228         Cvar_RegisterVariable(&r_useinfinitefarclip);
4229         Cvar_RegisterVariable(&r_farclip_base);
4230         Cvar_RegisterVariable(&r_farclip_world);
4231         Cvar_RegisterVariable(&r_nearclip);
4232         Cvar_RegisterVariable(&r_deformvertexes);
4233         Cvar_RegisterVariable(&r_transparent);
4234         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4235         Cvar_RegisterVariable(&r_showoverdraw);
4236         Cvar_RegisterVariable(&r_showbboxes);
4237         Cvar_RegisterVariable(&r_showsurfaces);
4238         Cvar_RegisterVariable(&r_showtris);
4239         Cvar_RegisterVariable(&r_shownormals);
4240         Cvar_RegisterVariable(&r_showlighting);
4241         Cvar_RegisterVariable(&r_showshadowvolumes);
4242         Cvar_RegisterVariable(&r_showcollisionbrushes);
4243         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4244         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4245         Cvar_RegisterVariable(&r_showdisabledepthtest);
4246         Cvar_RegisterVariable(&r_drawportals);
4247         Cvar_RegisterVariable(&r_drawentities);
4248         Cvar_RegisterVariable(&r_draw2d);
4249         Cvar_RegisterVariable(&r_drawworld);
4250         Cvar_RegisterVariable(&r_cullentities_trace);
4251         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4252         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4253         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4254         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4255         Cvar_RegisterVariable(&r_sortentities);
4256         Cvar_RegisterVariable(&r_drawviewmodel);
4257         Cvar_RegisterVariable(&r_drawexteriormodel);
4258         Cvar_RegisterVariable(&r_speeds);
4259         Cvar_RegisterVariable(&r_fullbrights);
4260         Cvar_RegisterVariable(&r_wateralpha);
4261         Cvar_RegisterVariable(&r_dynamic);
4262         Cvar_RegisterVariable(&r_fakelight);
4263         Cvar_RegisterVariable(&r_fakelight_intensity);
4264         Cvar_RegisterVariable(&r_fullbright);
4265         Cvar_RegisterVariable(&r_shadows);
4266         Cvar_RegisterVariable(&r_shadows_darken);
4267         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4268         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4269         Cvar_RegisterVariable(&r_shadows_throwdistance);
4270         Cvar_RegisterVariable(&r_shadows_throwdirection);
4271         Cvar_RegisterVariable(&r_shadows_focus);
4272         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4273         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4274         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4275         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4276         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4277         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4278         Cvar_RegisterVariable(&r_fog_exp2);
4279         Cvar_RegisterVariable(&r_fog_clear);
4280         Cvar_RegisterVariable(&r_drawfog);
4281         Cvar_RegisterVariable(&r_transparentdepthmasking);
4282         Cvar_RegisterVariable(&r_transparent_sortmindist);
4283         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4284         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4285         Cvar_RegisterVariable(&r_texture_dds_load);
4286         Cvar_RegisterVariable(&r_texture_dds_save);
4287         Cvar_RegisterVariable(&r_textureunits);
4288         Cvar_RegisterVariable(&gl_combine);
4289         Cvar_RegisterVariable(&r_viewfbo);
4290         Cvar_RegisterVariable(&r_viewscale);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4293         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4294         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4295         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4296         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4297         Cvar_RegisterVariable(&r_glsl);
4298         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4302         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4303         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4304         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4305         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4306         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4307         Cvar_RegisterVariable(&r_glsl_postprocess);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4312         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4313         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4314         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4315         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4316
4317         Cvar_RegisterVariable(&r_water);
4318         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4319         Cvar_RegisterVariable(&r_water_clippingplanebias);
4320         Cvar_RegisterVariable(&r_water_refractdistort);
4321         Cvar_RegisterVariable(&r_water_reflectdistort);
4322         Cvar_RegisterVariable(&r_water_scissormode);
4323         Cvar_RegisterVariable(&r_water_lowquality);
4324
4325         Cvar_RegisterVariable(&r_lerpsprites);
4326         Cvar_RegisterVariable(&r_lerpmodels);
4327         Cvar_RegisterVariable(&r_lerplightstyles);
4328         Cvar_RegisterVariable(&r_waterscroll);
4329         Cvar_RegisterVariable(&r_bloom);
4330         Cvar_RegisterVariable(&r_bloom_colorscale);
4331         Cvar_RegisterVariable(&r_bloom_brighten);
4332         Cvar_RegisterVariable(&r_bloom_blur);
4333         Cvar_RegisterVariable(&r_bloom_resolution);
4334         Cvar_RegisterVariable(&r_bloom_colorexponent);
4335         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4336         Cvar_RegisterVariable(&r_hdr);
4337         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4338         Cvar_RegisterVariable(&r_hdr_glowintensity);
4339         Cvar_RegisterVariable(&r_hdr_range);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4345         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4346         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4347         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4348         Cvar_RegisterVariable(&developer_texturelogging);
4349         Cvar_RegisterVariable(&gl_lightmaps);
4350         Cvar_RegisterVariable(&r_test);
4351         Cvar_RegisterVariable(&r_glsl_saturation);
4352         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4353         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4354         Cvar_RegisterVariable(&r_framedatasize);
4355         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4356                 Cvar_SetValue("r_fullbrights", 0);
4357         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4358 }
4359
4360 extern void R_Textures_Init(void);
4361 extern void GL_Draw_Init(void);
4362 extern void GL_Main_Init(void);
4363 extern void R_Shadow_Init(void);
4364 extern void R_Sky_Init(void);
4365 extern void GL_Surf_Init(void);
4366 extern void R_Particles_Init(void);
4367 extern void R_Explosion_Init(void);
4368 extern void gl_backend_init(void);
4369 extern void Sbar_Init(void);
4370 extern void R_LightningBeams_Init(void);
4371 extern void Mod_RenderInit(void);
4372 extern void Font_Init(void);
4373
4374 void Render_Init(void)
4375 {
4376         gl_backend_init();
4377         R_Textures_Init();
4378         GL_Main_Init();
4379         Font_Init();
4380         GL_Draw_Init();
4381         R_Shadow_Init();
4382         R_Sky_Init();
4383         GL_Surf_Init();
4384         Sbar_Init();
4385         R_Particles_Init();
4386         R_Explosion_Init();
4387         R_LightningBeams_Init();
4388         Mod_RenderInit();
4389 }
4390
4391 /*
4392 ===============
4393 GL_Init
4394 ===============
4395 */
4396 #ifndef USE_GLES2
4397 extern char *ENGINE_EXTENSIONS;
4398 void GL_Init (void)
4399 {
4400         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4401         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4402         gl_version = (const char *)qglGetString(GL_VERSION);
4403         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4404
4405         if (!gl_extensions)
4406                 gl_extensions = "";
4407         if (!gl_platformextensions)
4408                 gl_platformextensions = "";
4409
4410         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4411         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4412         Con_Printf("GL_VERSION: %s\n", gl_version);
4413         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4414         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4415
4416         VID_CheckExtensions();
4417
4418         // LordHavoc: report supported extensions
4419         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4420
4421         // clear to black (loading plaque will be seen over this)
4422         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4423 }
4424 #endif
4425
4426 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4427 {
4428         int i;
4429         mplane_t *p;
4430         if (r_trippy.integer)
4431                 return false;
4432         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4433         {
4434                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4435                 if (i == 4)
4436                         continue;
4437                 p = r_refdef.view.frustum + i;
4438                 switch(p->signbits)
4439                 {
4440                 default:
4441                 case 0:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 1:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 2:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 3:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 4:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 5:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 case 6:
4466                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4467                                 return true;
4468                         break;
4469                 case 7:
4470                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4471                                 return true;
4472                         break;
4473                 }
4474         }
4475         return false;
4476 }
4477
4478 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4479 {
4480         int i;
4481         const mplane_t *p;
4482         if (r_trippy.integer)
4483                 return false;
4484         for (i = 0;i < numplanes;i++)
4485         {
4486                 p = planes + i;
4487                 switch(p->signbits)
4488                 {
4489                 default:
4490                 case 0:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 1:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 2:
4499                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 case 3:
4503                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4504                                 return true;
4505                         break;
4506                 case 4:
4507                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4508                                 return true;
4509                         break;
4510                 case 5:
4511                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4512                                 return true;
4513                         break;
4514                 case 6:
4515                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4516                                 return true;
4517                         break;
4518                 case 7:
4519                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4520                                 return true;
4521                         break;
4522                 }
4523         }
4524         return false;
4525 }
4526
4527 //==================================================================================
4528
4529 // LordHavoc: this stores temporary data used within the same frame
4530
4531 typedef struct r_framedata_mem_s
4532 {
4533         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4534         size_t size; // how much usable space
4535         size_t current; // how much space in use
4536         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4537         size_t wantedsize; // how much space was allocated
4538         unsigned char *data; // start of real data (16byte aligned)
4539 }
4540 r_framedata_mem_t;
4541
4542 static r_framedata_mem_t *r_framedata_mem;
4543
4544 void R_FrameData_Reset(void)
4545 {
4546         while (r_framedata_mem)
4547         {
4548                 r_framedata_mem_t *next = r_framedata_mem->purge;
4549                 Mem_Free(r_framedata_mem);
4550                 r_framedata_mem = next;
4551         }
4552 }
4553
4554 void R_FrameData_Resize(void)
4555 {
4556         size_t wantedsize;
4557         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4558         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4559         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4560         {
4561                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4562                 newmem->wantedsize = wantedsize;
4563                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4564                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4565                 newmem->current = 0;
4566                 newmem->mark = 0;
4567                 newmem->purge = r_framedata_mem;
4568                 r_framedata_mem = newmem;
4569         }
4570 }
4571
4572 void R_FrameData_NewFrame(void)
4573 {
4574         R_FrameData_Resize();
4575         if (!r_framedata_mem)
4576                 return;
4577         // if we ran out of space on the last frame, free the old memory now
4578         while (r_framedata_mem->purge)
4579         {
4580                 // repeatedly remove the second item in the list, leaving only head
4581                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4582                 Mem_Free(r_framedata_mem->purge);
4583                 r_framedata_mem->purge = next;
4584         }
4585         // reset the current mem pointer
4586         r_framedata_mem->current = 0;
4587         r_framedata_mem->mark = 0;
4588 }
4589
4590 void *R_FrameData_Alloc(size_t size)
4591 {
4592         void *data;
4593
4594         // align to 16 byte boundary - the data pointer is already aligned, so we
4595         // only need to ensure the size of every allocation is also aligned
4596         size = (size + 15) & ~15;
4597
4598         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4599         {
4600                 // emergency - we ran out of space, allocate more memory
4601                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4602                 R_FrameData_Resize();
4603         }
4604
4605         data = r_framedata_mem->data + r_framedata_mem->current;
4606         r_framedata_mem->current += size;
4607
4608         // count the usage for stats
4609         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4610         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4611
4612         return (void *)data;
4613 }
4614
4615 void *R_FrameData_Store(size_t size, void *data)
4616 {
4617         void *d = R_FrameData_Alloc(size);
4618         if (d && data)
4619                 memcpy(d, data, size);
4620         return d;
4621 }
4622
4623 void R_FrameData_SetMark(void)
4624 {
4625         if (!r_framedata_mem)
4626                 return;
4627         r_framedata_mem->mark = r_framedata_mem->current;
4628 }
4629
4630 void R_FrameData_ReturnToMark(void)
4631 {
4632         if (!r_framedata_mem)
4633                 return;
4634         r_framedata_mem->current = r_framedata_mem->mark;
4635 }
4636
4637 //==================================================================================
4638
4639 // LordHavoc: animcache originally written by Echon, rewritten since then
4640
4641 /**
4642  * Animation cache prevents re-generating mesh data for an animated model
4643  * multiple times in one frame for lighting, shadowing, reflections, etc.
4644  */
4645
4646 void R_AnimCache_Free(void)
4647 {
4648 }
4649
4650 void R_AnimCache_ClearCache(void)
4651 {
4652         int i;
4653         entity_render_t *ent;
4654
4655         for (i = 0;i < r_refdef.scene.numentities;i++)
4656         {
4657                 ent = r_refdef.scene.entities[i];
4658                 ent->animcache_vertex3f = NULL;
4659                 ent->animcache_normal3f = NULL;
4660                 ent->animcache_svector3f = NULL;
4661                 ent->animcache_tvector3f = NULL;
4662                 ent->animcache_vertexmesh = NULL;
4663                 ent->animcache_vertex3fbuffer = NULL;
4664                 ent->animcache_vertexmeshbuffer = NULL;
4665         }
4666 }
4667
4668 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4669 {
4670         int i;
4671
4672         // check if we need the meshbuffers
4673         if (!vid.useinterleavedarrays)
4674                 return;
4675
4676         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4677                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4678         // TODO: upload vertex3f buffer?
4679         if (ent->animcache_vertexmesh)
4680         {
4681                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4682                 for (i = 0;i < numvertices;i++)
4683                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4684                 if (ent->animcache_svector3f)
4685                         for (i = 0;i < numvertices;i++)
4686                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4687                 if (ent->animcache_tvector3f)
4688                         for (i = 0;i < numvertices;i++)
4689                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4690                 if (ent->animcache_normal3f)
4691                         for (i = 0;i < numvertices;i++)
4692                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4693                 // TODO: upload vertexmeshbuffer?
4694         }
4695 }
4696
4697 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4698 {
4699         dp_model_t *model = ent->model;
4700         int numvertices;
4701         // see if it's already cached this frame
4702         if (ent->animcache_vertex3f)
4703         {
4704                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4705                 if (wantnormals || wanttangents)
4706                 {
4707                         if (ent->animcache_normal3f)
4708                                 wantnormals = false;
4709                         if (ent->animcache_svector3f)
4710                                 wanttangents = false;
4711                         if (wantnormals || wanttangents)
4712                         {
4713                                 numvertices = model->surfmesh.num_vertices;
4714                                 if (wantnormals)
4715                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4716                                 if (wanttangents)
4717                                 {
4718                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720                                 }
4721                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4722                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4723                         }
4724                 }
4725         }
4726         else
4727         {
4728                 // see if this ent is worth caching
4729                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4730                         return false;
4731                 // get some memory for this entity and generate mesh data
4732                 numvertices = model->surfmesh.num_vertices;
4733                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4734                 if (wantnormals)
4735                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4736                 if (wanttangents)
4737                 {
4738                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4739                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4740                 }
4741                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4742                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4743         }
4744         return true;
4745 }
4746
4747 void R_AnimCache_CacheVisibleEntities(void)
4748 {
4749         int i;
4750         qboolean wantnormals = true;
4751         qboolean wanttangents = !r_showsurfaces.integer;
4752
4753         switch(vid.renderpath)
4754         {
4755         case RENDERPATH_GL20:
4756         case RENDERPATH_D3D9:
4757         case RENDERPATH_D3D10:
4758         case RENDERPATH_D3D11:
4759         case RENDERPATH_GLES2:
4760                 break;
4761         case RENDERPATH_GL11:
4762         case RENDERPATH_GL13:
4763         case RENDERPATH_GLES1:
4764                 wanttangents = false;
4765                 break;
4766         case RENDERPATH_SOFT:
4767                 break;
4768         }
4769
4770         if (r_shownormals.integer)
4771                 wanttangents = wantnormals = true;
4772
4773         // TODO: thread this
4774         // NOTE: R_PrepareRTLights() also caches entities
4775
4776         for (i = 0;i < r_refdef.scene.numentities;i++)
4777                 if (r_refdef.viewcache.entityvisible[i])
4778                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4779 }
4780
4781 //==================================================================================
4782
4783 extern cvar_t r_overheadsprites_pushback;
4784
4785 static void R_View_UpdateEntityLighting (void)
4786 {
4787         int i;
4788         entity_render_t *ent;
4789         vec3_t tempdiffusenormal, avg;
4790         vec_t f, fa, fd, fdd;
4791         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4792
4793         for (i = 0;i < r_refdef.scene.numentities;i++)
4794         {
4795                 ent = r_refdef.scene.entities[i];
4796
4797                 // skip unseen models
4798                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4799                         continue;
4800
4801                 // skip bsp models
4802                 if (ent->model && ent->model->brush.num_leafs)
4803                 {
4804                         // TODO: use modellight for r_ambient settings on world?
4805                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4806                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4807                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4808                         continue;
4809                 }
4810
4811                 // fetch the lighting from the worldmodel data
4812                 VectorClear(ent->modellight_ambient);
4813                 VectorClear(ent->modellight_diffuse);
4814                 VectorClear(tempdiffusenormal);
4815                 if (ent->flags & RENDER_LIGHT)
4816                 {
4817                         vec3_t org;
4818                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4819
4820                         // complete lightning for lit sprites
4821                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4822                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4823                         {
4824                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4825                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4826                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4827                         }
4828                         else
4829                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4830
4831                         if(ent->flags & RENDER_EQUALIZE)
4832                         {
4833                                 // first fix up ambient lighting...
4834                                 if(r_equalize_entities_minambient.value > 0)
4835                                 {
4836                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4837                                         if(fd > 0)
4838                                         {
4839                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4840                                                 if(fa < r_equalize_entities_minambient.value * fd)
4841                                                 {
4842                                                         // solve:
4843                                                         //   fa'/fd' = minambient
4844                                                         //   fa'+0.25*fd' = fa+0.25*fd
4845                                                         //   ...
4846                                                         //   fa' = fd' * minambient
4847                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4848                                                         //   ...
4849                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4850                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4851                                                         //   ...
4852                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4853                                                         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
4854                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4855                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4856                                                 }
4857                                         }
4858                                 }
4859
4860                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4861                                 {
4862                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4863                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4864                                         f = fa + 0.25 * fd;
4865                                         if(f > 0)
4866                                         {
4867                                                 // adjust brightness and saturation to target
4868                                                 avg[0] = avg[1] = avg[2] = fa / f;
4869                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4870                                                 avg[0] = avg[1] = avg[2] = fd / f;
4871                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4872                                         }
4873                                 }
4874                         }
4875                 }
4876                 else // highly rare
4877                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4878
4879                 // move the light direction into modelspace coordinates for lighting code
4880                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4881                 if(VectorLength2(ent->modellight_lightdir) == 0)
4882                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4883                 VectorNormalize(ent->modellight_lightdir);
4884         }
4885 }
4886
4887 #define MAX_LINEOFSIGHTTRACES 64
4888
4889 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4890 {
4891         int i;
4892         vec3_t boxmins, boxmaxs;
4893         vec3_t start;
4894         vec3_t end;
4895         dp_model_t *model = r_refdef.scene.worldmodel;
4896
4897         if (!model || !model->brush.TraceLineOfSight)
4898                 return true;
4899
4900         // expand the box a little
4901         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4902         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4903         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4904         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4905         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4906         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4907
4908         // return true if eye is inside enlarged box
4909         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4910                 return true;
4911
4912         // try center
4913         VectorCopy(eye, start);
4914         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4915         if (model->brush.TraceLineOfSight(model, start, end))
4916                 return true;
4917
4918         // try various random positions
4919         for (i = 0;i < numsamples;i++)
4920         {
4921                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4922                 if (model->brush.TraceLineOfSight(model, start, end))
4923                         return true;
4924         }
4925
4926         return false;
4927 }
4928
4929
4930 static void R_View_UpdateEntityVisible (void)
4931 {
4932         int i;
4933         int renderimask;
4934         int samples;
4935         entity_render_t *ent;
4936
4937         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4938                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4939                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4940                 :                                                          RENDER_EXTERIORMODEL;
4941         if (!r_drawviewmodel.integer)
4942                 renderimask |= RENDER_VIEWMODEL;
4943         if (!r_drawexteriormodel.integer)
4944                 renderimask |= RENDER_EXTERIORMODEL;
4945         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4946         {
4947                 // worldmodel can check visibility
4948                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4949                 for (i = 0;i < r_refdef.scene.numentities;i++)
4950                 {
4951                         ent = r_refdef.scene.entities[i];
4952                         if (!(ent->flags & renderimask))
4953                         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)))
4954                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4955                                 r_refdef.viewcache.entityvisible[i] = true;
4956                 }
4957         }
4958         else
4959         {
4960                 // no worldmodel or it can't check visibility
4961                 for (i = 0;i < r_refdef.scene.numentities;i++)
4962                 {
4963                         ent = r_refdef.scene.entities[i];
4964                         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));
4965                 }
4966         }
4967         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4968                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4969         {
4970                 for (i = 0;i < r_refdef.scene.numentities;i++)
4971                 {
4972                         if (!r_refdef.viewcache.entityvisible[i])
4973                                 continue;
4974                         ent = r_refdef.scene.entities[i];
4975                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4976                         {
4977                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4978                                 if (samples < 0)
4979                                         continue; // temp entities do pvs only
4980                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4981                                         ent->last_trace_visibility = realtime;
4982                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4983                                         r_refdef.viewcache.entityvisible[i] = 0;
4984                         }
4985                 }
4986         }
4987 }
4988
4989 /// only used if skyrendermasked, and normally returns false
4990 int R_DrawBrushModelsSky (void)
4991 {
4992         int i, sky;
4993         entity_render_t *ent;
4994
4995         sky = false;
4996         for (i = 0;i < r_refdef.scene.numentities;i++)
4997         {
4998                 if (!r_refdef.viewcache.entityvisible[i])
4999                         continue;
5000                 ent = r_refdef.scene.entities[i];
5001                 if (!ent->model || !ent->model->DrawSky)
5002                         continue;
5003                 ent->model->DrawSky(ent);
5004                 sky = true;
5005         }
5006         return sky;
5007 }
5008
5009 static void R_DrawNoModel(entity_render_t *ent);
5010 static void R_DrawModels(void)
5011 {
5012         int i;
5013         entity_render_t *ent;
5014
5015         for (i = 0;i < r_refdef.scene.numentities;i++)
5016         {
5017                 if (!r_refdef.viewcache.entityvisible[i])
5018                         continue;
5019                 ent = r_refdef.scene.entities[i];
5020                 r_refdef.stats.entities++;
5021                 /*
5022                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5023                 {
5024                         vec3_t f, l, u, o;
5025                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5026                         Con_Printf("R_DrawModels\n");
5027                         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]);
5028                         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);
5029                         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);
5030                 }
5031                 */
5032                 if (ent->model && ent->model->Draw != NULL)
5033                         ent->model->Draw(ent);
5034                 else
5035                         R_DrawNoModel(ent);
5036         }
5037 }
5038
5039 static void R_DrawModelsDepth(void)
5040 {
5041         int i;
5042         entity_render_t *ent;
5043
5044         for (i = 0;i < r_refdef.scene.numentities;i++)
5045         {
5046                 if (!r_refdef.viewcache.entityvisible[i])
5047                         continue;
5048                 ent = r_refdef.scene.entities[i];
5049                 if (ent->model && ent->model->DrawDepth != NULL)
5050                         ent->model->DrawDepth(ent);
5051         }
5052 }
5053
5054 static void R_DrawModelsDebug(void)
5055 {
5056         int i;
5057         entity_render_t *ent;
5058
5059         for (i = 0;i < r_refdef.scene.numentities;i++)
5060         {
5061                 if (!r_refdef.viewcache.entityvisible[i])
5062                         continue;
5063                 ent = r_refdef.scene.entities[i];
5064                 if (ent->model && ent->model->DrawDebug != NULL)
5065                         ent->model->DrawDebug(ent);
5066         }
5067 }
5068
5069 static void R_DrawModelsAddWaterPlanes(void)
5070 {
5071         int i;
5072         entity_render_t *ent;
5073
5074         for (i = 0;i < r_refdef.scene.numentities;i++)
5075         {
5076                 if (!r_refdef.viewcache.entityvisible[i])
5077                         continue;
5078                 ent = r_refdef.scene.entities[i];
5079                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5080                         ent->model->DrawAddWaterPlanes(ent);
5081         }
5082 }
5083
5084 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5085 {
5086         if (r_hdr_irisadaptation.integer)
5087         {
5088                 vec3_t ambient;
5089                 vec3_t diffuse;
5090                 vec3_t diffusenormal;
5091                 vec_t brightness;
5092                 vec_t goal;
5093                 vec_t current;
5094                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5095                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5096                 brightness = max(0.0000001f, brightness);
5097                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5098                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5099                 current = r_hdr_irisadaptation_value.value;
5100                 if (current < goal)
5101                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5102                 else if (current > goal)
5103                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5104                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5105                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5106         }
5107         else if (r_hdr_irisadaptation_value.value != 1.0f)
5108                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5109 }
5110
5111 static void R_View_SetFrustum(const int *scissor)
5112 {
5113         int i;
5114         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5115         vec3_t forward, left, up, origin, v;
5116
5117         if(scissor)
5118         {
5119                 // flipped x coordinates (because x points left here)
5120                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5121                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5122
5123                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5124                 switch(vid.renderpath)
5125                 {
5126                         case RENDERPATH_D3D9:
5127                         case RENDERPATH_D3D10:
5128                         case RENDERPATH_D3D11:
5129                                 // non-flipped y coordinates
5130                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5131                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5132                                 break;
5133                         case RENDERPATH_SOFT:
5134                         case RENDERPATH_GL11:
5135                         case RENDERPATH_GL13:
5136                         case RENDERPATH_GL20:
5137                         case RENDERPATH_GLES1:
5138                         case RENDERPATH_GLES2:
5139                                 // non-flipped y coordinates
5140                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5141                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5142                                 break;
5143                 }
5144         }
5145
5146         // we can't trust r_refdef.view.forward and friends in reflected scenes
5147         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5148
5149 #if 0
5150         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5151         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5152         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5153         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5154         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5155         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5156         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5157         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5158         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5159         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5160         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5161         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5162 #endif
5163
5164 #if 0
5165         zNear = r_refdef.nearclip;
5166         nudge = 1.0 - 1.0 / (1<<23);
5167         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5168         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5169         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5170         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5171         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5172         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5173         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5174         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5175 #endif
5176
5177
5178
5179 #if 0
5180         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5181         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5182         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5183         r_refdef.view.frustum[0].dist = m[15] - m[12];
5184
5185         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5186         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5187         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5188         r_refdef.view.frustum[1].dist = m[15] + m[12];
5189
5190         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5191         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5192         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5193         r_refdef.view.frustum[2].dist = m[15] - m[13];
5194
5195         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5196         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5197         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5198         r_refdef.view.frustum[3].dist = m[15] + m[13];
5199
5200         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5201         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5202         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5203         r_refdef.view.frustum[4].dist = m[15] - m[14];
5204
5205         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5206         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5207         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5208         r_refdef.view.frustum[5].dist = m[15] + m[14];
5209 #endif
5210
5211         if (r_refdef.view.useperspective)
5212         {
5213                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5214                 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]);
5215                 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]);
5216                 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]);
5217                 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]);
5218
5219                 // then the normals from the corners relative to origin
5220                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5221                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5222                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5223                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5224
5225                 // in a NORMAL view, forward cross left == up
5226                 // in a REFLECTED view, forward cross left == down
5227                 // so our cross products above need to be adjusted for a left handed coordinate system
5228                 CrossProduct(forward, left, v);
5229                 if(DotProduct(v, up) < 0)
5230                 {
5231                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5232                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5233                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5234                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5235                 }
5236
5237                 // Leaving those out was a mistake, those were in the old code, and they
5238                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5239                 // I couldn't reproduce it after adding those normalizations. --blub
5240                 VectorNormalize(r_refdef.view.frustum[0].normal);
5241                 VectorNormalize(r_refdef.view.frustum[1].normal);
5242                 VectorNormalize(r_refdef.view.frustum[2].normal);
5243                 VectorNormalize(r_refdef.view.frustum[3].normal);
5244
5245                 // make the corners absolute
5246                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5247                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5248                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5249                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5250
5251                 // one more normal
5252                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5253
5254                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5255                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5256                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5257                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5258                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5259         }
5260         else
5261         {
5262                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5263                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5264                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5265                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5266                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5267                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5268                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5269                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5270                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5271                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5272         }
5273         r_refdef.view.numfrustumplanes = 5;
5274
5275         if (r_refdef.view.useclipplane)
5276         {
5277                 r_refdef.view.numfrustumplanes = 6;
5278                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5279         }
5280
5281         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5282                 PlaneClassify(r_refdef.view.frustum + i);
5283
5284         // LordHavoc: note to all quake engine coders, Quake had a special case
5285         // for 90 degrees which assumed a square view (wrong), so I removed it,
5286         // Quake2 has it disabled as well.
5287
5288         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5289         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5290         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5291         //PlaneClassify(&frustum[0]);
5292
5293         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5294         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5295         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5296         //PlaneClassify(&frustum[1]);
5297
5298         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5299         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5300         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5301         //PlaneClassify(&frustum[2]);
5302
5303         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5304         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5305         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5306         //PlaneClassify(&frustum[3]);
5307
5308         // nearclip plane
5309         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5310         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5311         //PlaneClassify(&frustum[4]);
5312 }
5313
5314 void R_View_UpdateWithScissor(const int *myscissor)
5315 {
5316         R_Main_ResizeViewCache();
5317         R_View_SetFrustum(myscissor);
5318         R_View_WorldVisibility(r_refdef.view.useclipplane);
5319         R_View_UpdateEntityVisible();
5320         R_View_UpdateEntityLighting();
5321 }
5322
5323 void R_View_Update(void)
5324 {
5325         R_Main_ResizeViewCache();
5326         R_View_SetFrustum(NULL);
5327         R_View_WorldVisibility(r_refdef.view.useclipplane);
5328         R_View_UpdateEntityVisible();
5329         R_View_UpdateEntityLighting();
5330 }
5331
5332 float viewscalefpsadjusted = 1.0f;
5333
5334 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5335 {
5336         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5337         scale = bound(0.03125f, scale, 1.0f);
5338         *outwidth = (int)ceil(width * scale);
5339         *outheight = (int)ceil(height * scale);
5340 }
5341
5342 void R_Mesh_SetMainRenderTargets(void)
5343 {
5344         if (r_bloomstate.fbo_framebuffer)
5345                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5346         else
5347                 R_Mesh_ResetRenderTargets();
5348 }
5349
5350 void R_SetupView(qboolean allowwaterclippingplane)
5351 {
5352         const float *customclipplane = NULL;
5353         float plane[4];
5354         int scaledwidth, scaledheight;
5355         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5356         {
5357                 // LordHavoc: couldn't figure out how to make this approach the
5358                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5359                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5360                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5361                         dist = r_refdef.view.clipplane.dist;
5362                 plane[0] = r_refdef.view.clipplane.normal[0];
5363                 plane[1] = r_refdef.view.clipplane.normal[1];
5364                 plane[2] = r_refdef.view.clipplane.normal[2];
5365                 plane[3] = -dist;
5366                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5367         }
5368
5369         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5370         if (!r_refdef.view.useperspective)
5371                 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);
5372         else if (vid.stencil && r_useinfinitefarclip.integer)
5373                 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);
5374         else
5375                 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);
5376         R_Mesh_SetMainRenderTargets();
5377         R_SetViewport(&r_refdef.view.viewport);
5378         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5379         {
5380                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5381                 float screenplane[4];
5382                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5383                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5384                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5385                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5386                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5387         }
5388 }
5389
5390 void R_EntityMatrix(const matrix4x4_t *matrix)
5391 {
5392         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5393         {
5394                 gl_modelmatrixchanged = false;
5395                 gl_modelmatrix = *matrix;
5396                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5397                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5398                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5399                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5400                 CHECKGLERROR
5401                 switch(vid.renderpath)
5402                 {
5403                 case RENDERPATH_D3D9:
5404 #ifdef SUPPORTD3D
5405                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5406                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5407 #endif
5408                         break;
5409                 case RENDERPATH_D3D10:
5410                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5411                         break;
5412                 case RENDERPATH_D3D11:
5413                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5414                         break;
5415                 case RENDERPATH_GL11:
5416                 case RENDERPATH_GL13:
5417                 case RENDERPATH_GLES1:
5418                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5419                         break;
5420                 case RENDERPATH_SOFT:
5421                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5422                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5423                         break;
5424                 case RENDERPATH_GL20:
5425                 case RENDERPATH_GLES2:
5426                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5427                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5428                         break;
5429                 }
5430         }
5431 }
5432
5433 void R_ResetViewRendering2D(void)
5434 {
5435         r_viewport_t viewport;
5436         DrawQ_Finish();
5437
5438         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5439         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);
5440         R_Mesh_ResetRenderTargets();
5441         R_SetViewport(&viewport);
5442         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5443         GL_Color(1, 1, 1, 1);
5444         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5445         GL_BlendFunc(GL_ONE, GL_ZERO);
5446         GL_ScissorTest(false);
5447         GL_DepthMask(false);
5448         GL_DepthRange(0, 1);
5449         GL_DepthTest(false);
5450         GL_DepthFunc(GL_LEQUAL);
5451         R_EntityMatrix(&identitymatrix);
5452         R_Mesh_ResetTextureState();
5453         GL_PolygonOffset(0, 0);
5454         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5455         switch(vid.renderpath)
5456         {
5457         case RENDERPATH_GL11:
5458         case RENDERPATH_GL13:
5459         case RENDERPATH_GL20:
5460         case RENDERPATH_GLES1:
5461         case RENDERPATH_GLES2:
5462                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5463                 break;
5464         case RENDERPATH_D3D9:
5465         case RENDERPATH_D3D10:
5466         case RENDERPATH_D3D11:
5467         case RENDERPATH_SOFT:
5468                 break;
5469         }
5470         GL_CullFace(GL_NONE);
5471 }
5472
5473 void R_ResetViewRendering3D(void)
5474 {
5475         DrawQ_Finish();
5476
5477         R_SetupView(true);
5478         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5479         GL_Color(1, 1, 1, 1);
5480         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5481         GL_BlendFunc(GL_ONE, GL_ZERO);
5482         GL_ScissorTest(true);
5483         GL_DepthMask(true);
5484         GL_DepthRange(0, 1);
5485         GL_DepthTest(true);
5486         GL_DepthFunc(GL_LEQUAL);
5487         R_EntityMatrix(&identitymatrix);
5488         R_Mesh_ResetTextureState();
5489         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5490         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5491         switch(vid.renderpath)
5492         {
5493         case RENDERPATH_GL11:
5494         case RENDERPATH_GL13:
5495         case RENDERPATH_GL20:
5496         case RENDERPATH_GLES1:
5497         case RENDERPATH_GLES2:
5498                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5499                 break;
5500         case RENDERPATH_D3D9:
5501         case RENDERPATH_D3D10:
5502         case RENDERPATH_D3D11:
5503         case RENDERPATH_SOFT:
5504                 break;
5505         }
5506         GL_CullFace(r_refdef.view.cullface_back);
5507 }
5508
5509 /*
5510 ================
5511 R_RenderView_UpdateViewVectors
5512 ================
5513 */
5514 static void R_RenderView_UpdateViewVectors(void)
5515 {
5516         // break apart the view matrix into vectors for various purposes
5517         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5518         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5519         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5520         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5521         // make an inverted copy of the view matrix for tracking sprites
5522         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5523 }
5524
5525 void R_RenderScene(void);
5526 void R_RenderWaterPlanes(void);
5527
5528 static void R_Water_StartFrame(void)
5529 {
5530         int i;
5531         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5532         r_waterstate_waterplane_t *p;
5533
5534         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5535                 return;
5536
5537         switch(vid.renderpath)
5538         {
5539         case RENDERPATH_GL20:
5540         case RENDERPATH_D3D9:
5541         case RENDERPATH_D3D10:
5542         case RENDERPATH_D3D11:
5543         case RENDERPATH_SOFT:
5544         case RENDERPATH_GLES2:
5545                 break;
5546         case RENDERPATH_GL11:
5547         case RENDERPATH_GL13:
5548         case RENDERPATH_GLES1:
5549                 return;
5550         }
5551
5552         // set waterwidth and waterheight to the water resolution that will be
5553         // used (often less than the screen resolution for faster rendering)
5554         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5555
5556         // calculate desired texture sizes
5557         // can't use water if the card does not support the texture size
5558         if (!r_water.integer || r_showsurfaces.integer)
5559                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5560         else if (vid.support.arb_texture_non_power_of_two)
5561         {
5562                 texturewidth = waterwidth;
5563                 textureheight = waterheight;
5564                 camerawidth = waterwidth;
5565                 cameraheight = waterheight;
5566         }
5567         else
5568         {
5569                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5570                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5571                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5572                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5573         }
5574
5575         // allocate textures as needed
5576         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5577         {
5578                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5579                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5580                 {
5581                         if (p->texture_refraction)
5582                                 R_FreeTexture(p->texture_refraction);
5583                         p->texture_refraction = NULL;
5584                         if (p->texture_reflection)
5585                                 R_FreeTexture(p->texture_reflection);
5586                         p->texture_reflection = NULL;
5587                         if (p->texture_camera)
5588                                 R_FreeTexture(p->texture_camera);
5589                         p->texture_camera = NULL;
5590                 }
5591                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5592                 r_waterstate.texturewidth = texturewidth;
5593                 r_waterstate.textureheight = textureheight;
5594                 r_waterstate.camerawidth = camerawidth;
5595                 r_waterstate.cameraheight = cameraheight;
5596         }
5597
5598         if (r_waterstate.texturewidth)
5599         {
5600                 int scaledwidth, scaledheight;
5601
5602                 r_waterstate.enabled = true;
5603
5604                 // when doing a reduced render (HDR) we want to use a smaller area
5605                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5606                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5607                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5608
5609                 // set up variables that will be used in shader setup
5610                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5611                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5612                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5613                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5614         }
5615
5616         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5617         r_waterstate.numwaterplanes = 0;
5618 }
5619
5620 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5621 {
5622         int triangleindex, planeindex;
5623         const int *e;
5624         vec3_t vert[3];
5625         vec3_t normal;
5626         vec3_t center;
5627         mplane_t plane;
5628         r_waterstate_waterplane_t *p;
5629         texture_t *t = R_GetCurrentTexture(surface->texture);
5630
5631         // just use the first triangle with a valid normal for any decisions
5632         VectorClear(normal);
5633         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5634         {
5635                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5636                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5637                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5638                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5639                 if (VectorLength2(normal) >= 0.001)
5640                         break;
5641         }
5642
5643         VectorCopy(normal, plane.normal);
5644         VectorNormalize(plane.normal);
5645         plane.dist = DotProduct(vert[0], plane.normal);
5646         PlaneClassify(&plane);
5647         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5648         {
5649                 // skip backfaces (except if nocullface is set)
5650                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5651                         return;
5652                 VectorNegate(plane.normal, plane.normal);
5653                 plane.dist *= -1;
5654                 PlaneClassify(&plane);
5655         }
5656
5657
5658         // find a matching plane if there is one
5659         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5660                 if(p->camera_entity == t->camera_entity)
5661                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5662                                 break;
5663         if (planeindex >= r_waterstate.maxwaterplanes)
5664                 return; // nothing we can do, out of planes
5665
5666         // if this triangle does not fit any known plane rendered this frame, add one
5667         if (planeindex >= r_waterstate.numwaterplanes)
5668         {
5669                 // store the new plane
5670                 r_waterstate.numwaterplanes++;
5671                 p->plane = plane;
5672                 // clear materialflags and pvs
5673                 p->materialflags = 0;
5674                 p->pvsvalid = false;
5675                 p->camera_entity = t->camera_entity;
5676                 VectorCopy(surface->mins, p->mins);
5677                 VectorCopy(surface->maxs, p->maxs);
5678         }
5679         else
5680         {
5681                 // merge mins/maxs
5682                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5683                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5684                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5685                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5686                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5687                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5688         }
5689         // merge this surface's materialflags into the waterplane
5690         p->materialflags |= t->currentmaterialflags;
5691         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5692         {
5693                 // merge this surface's PVS into the waterplane
5694                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5695                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5696                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5697                 {
5698                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5699                         p->pvsvalid = true;
5700                 }
5701         }
5702 }
5703
5704 extern cvar_t r_drawparticles;
5705 extern cvar_t r_drawdecals;
5706
5707 static void R_Water_ProcessPlanes(void)
5708 {
5709         int myscissor[4];
5710         r_refdef_view_t originalview;
5711         r_refdef_view_t myview;
5712         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;
5713         r_waterstate_waterplane_t *p;
5714         vec3_t visorigin;
5715
5716         originalview = r_refdef.view;
5717
5718         // lowquality hack, temporarily shut down some cvars and restore afterwards
5719         qualityreduction = r_water_lowquality.integer;
5720         if (qualityreduction > 0)
5721         {
5722                 if (qualityreduction >= 1)
5723                 {
5724                         old_r_shadows = r_shadows.integer;
5725                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5726                         old_r_dlight = r_shadow_realtime_dlight.integer;
5727                         Cvar_SetValueQuick(&r_shadows, 0);
5728                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5729                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5730                 }
5731                 if (qualityreduction >= 2)
5732                 {
5733                         old_r_dynamic = r_dynamic.integer;
5734                         old_r_particles = r_drawparticles.integer;
5735                         old_r_decals = r_drawdecals.integer;
5736                         Cvar_SetValueQuick(&r_dynamic, 0);
5737                         Cvar_SetValueQuick(&r_drawparticles, 0);
5738                         Cvar_SetValueQuick(&r_drawdecals, 0);
5739                 }
5740         }
5741
5742         // make sure enough textures are allocated
5743         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5744         {
5745                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5746                 {
5747                         if (!p->texture_refraction)
5748                                 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);
5749                         if (!p->texture_refraction)
5750                                 goto error;
5751                 }
5752                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5753                 {
5754                         if (!p->texture_camera)
5755                                 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);
5756                         if (!p->texture_camera)
5757                                 goto error;
5758                 }
5759
5760                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5761                 {
5762                         if (!p->texture_reflection)
5763                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5764                         if (!p->texture_reflection)
5765                                 goto error;
5766                 }
5767         }
5768
5769         // render views
5770         r_refdef.view = originalview;
5771         r_refdef.view.showdebug = false;
5772         r_refdef.view.width = r_waterstate.waterwidth;
5773         r_refdef.view.height = r_waterstate.waterheight;
5774         r_refdef.view.useclipplane = true;
5775         myview = r_refdef.view;
5776         r_waterstate.renderingscene = true;
5777         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5778         {
5779                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5780                 {
5781                         r_refdef.view = myview;
5782                         if(r_water_scissormode.integer)
5783                         {
5784                                 R_SetupView(true);
5785                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5786                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5787                         }
5788
5789                         // render reflected scene and copy into texture
5790                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5791                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5792                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5793                         r_refdef.view.clipplane = p->plane;
5794                         // reverse the cullface settings for this render
5795                         r_refdef.view.cullface_front = GL_FRONT;
5796                         r_refdef.view.cullface_back = GL_BACK;
5797                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5798                         {
5799                                 r_refdef.view.usecustompvs = true;
5800                                 if (p->pvsvalid)
5801                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5802                                 else
5803                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5804                         }
5805
5806                         R_ResetViewRendering3D();
5807                         R_ClearScreen(r_refdef.fogenabled);
5808                         if(r_water_scissormode.integer & 2)
5809                                 R_View_UpdateWithScissor(myscissor);
5810                         else
5811                                 R_View_Update();
5812                         if(r_water_scissormode.integer & 1)
5813                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5814                         R_RenderScene();
5815
5816                         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);
5817                 }
5818
5819                 // render the normal view scene and copy into texture
5820                 // (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)
5821                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5822                 {
5823                         r_refdef.view = myview;
5824                         if(r_water_scissormode.integer)
5825                         {
5826                                 R_SetupView(true);
5827                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5828                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5829                         }
5830
5831                         r_waterstate.renderingrefraction = true;
5832
5833                         r_refdef.view.clipplane = p->plane;
5834                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5835                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5836
5837                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5838                         {
5839                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5840                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5841                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5842                                 R_RenderView_UpdateViewVectors();
5843                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5844                                 {
5845                                         r_refdef.view.usecustompvs = true;
5846                                         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);
5847                                 }
5848                         }
5849
5850                         PlaneClassify(&r_refdef.view.clipplane);
5851
5852                         R_ResetViewRendering3D();
5853                         R_ClearScreen(r_refdef.fogenabled);
5854                         if(r_water_scissormode.integer & 2)
5855                                 R_View_UpdateWithScissor(myscissor);
5856                         else
5857                                 R_View_Update();
5858                         if(r_water_scissormode.integer & 1)
5859                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5860                         R_RenderScene();
5861
5862                         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);
5863                         r_waterstate.renderingrefraction = false;
5864                 }
5865                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5866                 {
5867                         r_refdef.view = myview;
5868
5869                         r_refdef.view.clipplane = p->plane;
5870                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5871                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5872
5873                         r_refdef.view.width = r_waterstate.camerawidth;
5874                         r_refdef.view.height = r_waterstate.cameraheight;
5875                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5876                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5877
5878                         if(p->camera_entity)
5879                         {
5880                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5881                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5882                         }
5883
5884                         // note: all of the view is used for displaying... so
5885                         // there is no use in scissoring
5886
5887                         // reverse the cullface settings for this render
5888                         r_refdef.view.cullface_front = GL_FRONT;
5889                         r_refdef.view.cullface_back = GL_BACK;
5890                         // also reverse the view matrix
5891                         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
5892                         R_RenderView_UpdateViewVectors();
5893                         if(p->camera_entity && 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                         // camera needs no clipplane
5900                         r_refdef.view.useclipplane = false;
5901
5902                         PlaneClassify(&r_refdef.view.clipplane);
5903
5904                         R_ResetViewRendering3D();
5905                         R_ClearScreen(r_refdef.fogenabled);
5906                         R_View_Update();
5907                         R_RenderScene();
5908
5909                         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);
5910                         r_waterstate.renderingrefraction = false;
5911                 }
5912
5913         }
5914         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5915         r_waterstate.renderingscene = false;
5916         r_refdef.view = originalview;
5917         R_ResetViewRendering3D();
5918         R_ClearScreen(r_refdef.fogenabled);
5919         R_View_Update();
5920         goto finish;
5921 error:
5922         r_refdef.view = originalview;
5923         r_waterstate.renderingscene = false;
5924         Cvar_SetValueQuick(&r_water, 0);
5925         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5926 finish:
5927         // lowquality hack, restore cvars
5928         if (qualityreduction > 0)
5929         {
5930                 if (qualityreduction >= 1)
5931                 {
5932                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5933                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5934                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5935                 }
5936                 if (qualityreduction >= 2)
5937                 {
5938                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5939                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5940                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5941                 }
5942         }
5943 }
5944
5945 void R_Bloom_StartFrame(void)
5946 {
5947         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5948         int viewwidth, viewheight;
5949         textype_t textype;
5950
5951         if (r_viewscale_fpsscaling.integer)
5952         {
5953                 double actualframetime;
5954                 double targetframetime;
5955                 double adjust;
5956                 actualframetime = r_refdef.lastdrawscreentime;
5957                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5958                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5959                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5960                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5961                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5962                 viewscalefpsadjusted += adjust;
5963                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5964         }
5965         else
5966                 viewscalefpsadjusted = 1.0f;
5967
5968         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5969
5970         switch(vid.renderpath)
5971         {
5972         case RENDERPATH_GL20:
5973         case RENDERPATH_D3D9:
5974         case RENDERPATH_D3D10:
5975         case RENDERPATH_D3D11:
5976         case RENDERPATH_SOFT:
5977         case RENDERPATH_GLES2:
5978                 break;
5979         case RENDERPATH_GL11:
5980         case RENDERPATH_GL13:
5981         case RENDERPATH_GLES1:
5982                 return;
5983         }
5984
5985         // set bloomwidth and bloomheight to the bloom resolution that will be
5986         // used (often less than the screen resolution for faster rendering)
5987         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5988         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5989         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5990         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5991         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5992
5993         // calculate desired texture sizes
5994         if (vid.support.arb_texture_non_power_of_two)
5995         {
5996                 screentexturewidth = vid.width;
5997                 screentextureheight = vid.height;
5998                 bloomtexturewidth = r_bloomstate.bloomwidth;
5999                 bloomtextureheight = r_bloomstate.bloomheight;
6000         }
6001         else
6002         {
6003                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6004                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6005                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6006                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6007         }
6008
6009         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))
6010         {
6011                 Cvar_SetValueQuick(&r_hdr, 0);
6012                 Cvar_SetValueQuick(&r_bloom, 0);
6013                 Cvar_SetValueQuick(&r_motionblur, 0);
6014                 Cvar_SetValueQuick(&r_damageblur, 0);
6015         }
6016
6017         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)
6018                 screentexturewidth = screentextureheight = 0;
6019         if (!r_hdr.integer && !r_bloom.integer)
6020                 bloomtexturewidth = bloomtextureheight = 0;
6021
6022         textype = TEXTYPE_COLORBUFFER;
6023         switch (vid.renderpath)
6024         {
6025         case RENDERPATH_GL20:
6026         case RENDERPATH_GLES2:
6027                 if (vid.support.ext_framebuffer_object)
6028                 {
6029                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6030                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6031                 }
6032                 break;
6033         case RENDERPATH_GL11:
6034         case RENDERPATH_GL13:
6035         case RENDERPATH_GLES1:
6036         case RENDERPATH_D3D9:
6037         case RENDERPATH_D3D10:
6038         case RENDERPATH_D3D11:
6039         case RENDERPATH_SOFT:
6040                 break;
6041         }
6042
6043         // allocate textures as needed
6044         if (r_bloomstate.screentexturewidth != screentexturewidth
6045          || r_bloomstate.screentextureheight != screentextureheight
6046          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6047          || r_bloomstate.bloomtextureheight != bloomtextureheight
6048          || r_bloomstate.texturetype != textype
6049          || r_bloomstate.viewfbo != r_viewfbo.integer)
6050         {
6051                 if (r_bloomstate.texture_bloom)
6052                         R_FreeTexture(r_bloomstate.texture_bloom);
6053                 r_bloomstate.texture_bloom = NULL;
6054                 if (r_bloomstate.texture_screen)
6055                         R_FreeTexture(r_bloomstate.texture_screen);
6056                 r_bloomstate.texture_screen = NULL;
6057                 if (r_bloomstate.fbo_framebuffer)
6058                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6059                 r_bloomstate.fbo_framebuffer = 0;
6060                 if (r_bloomstate.texture_framebuffercolor)
6061                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6062                 r_bloomstate.texture_framebuffercolor = NULL;
6063                 if (r_bloomstate.texture_framebufferdepth)
6064                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6065                 r_bloomstate.texture_framebufferdepth = NULL;
6066                 r_bloomstate.screentexturewidth = screentexturewidth;
6067                 r_bloomstate.screentextureheight = screentextureheight;
6068                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6069                         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);
6070                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6071                 {
6072                         // FIXME: choose depth bits based on a cvar
6073                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6074                         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);
6075                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6076                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6077 #ifndef USE_GLES2
6078                         // render depth into one texture and normalmap into the other
6079                         if (qglDrawBuffer)
6080                         {
6081                                 int status;
6082                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6083                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6084                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6085                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6086                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6087                         }
6088 #endif
6089                 }
6090                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6091                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6092                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6093                         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);
6094                 r_bloomstate.viewfbo = r_viewfbo.integer;
6095                 r_bloomstate.texturetype = textype;
6096         }
6097
6098         // when doing a reduced render (HDR) we want to use a smaller area
6099         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6100         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6101         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6102         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6103         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6104
6105         // set up a texcoord array for the full resolution screen image
6106         // (we have to keep this around to copy back during final render)
6107         r_bloomstate.screentexcoord2f[0] = 0;
6108         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6109         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6110         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6111         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6112         r_bloomstate.screentexcoord2f[5] = 0;
6113         r_bloomstate.screentexcoord2f[6] = 0;
6114         r_bloomstate.screentexcoord2f[7] = 0;
6115
6116         // set up a texcoord array for the reduced resolution bloom image
6117         // (which will be additive blended over the screen image)
6118         r_bloomstate.bloomtexcoord2f[0] = 0;
6119         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6121         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6122         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6123         r_bloomstate.bloomtexcoord2f[5] = 0;
6124         r_bloomstate.bloomtexcoord2f[6] = 0;
6125         r_bloomstate.bloomtexcoord2f[7] = 0;
6126
6127         switch(vid.renderpath)
6128         {
6129         case RENDERPATH_GL11:
6130         case RENDERPATH_GL13:
6131         case RENDERPATH_GL20:
6132         case RENDERPATH_SOFT:
6133         case RENDERPATH_GLES1:
6134         case RENDERPATH_GLES2:
6135                 break;
6136         case RENDERPATH_D3D9:
6137         case RENDERPATH_D3D10:
6138         case RENDERPATH_D3D11:
6139                 {
6140                         int i;
6141                         for (i = 0;i < 4;i++)
6142                         {
6143                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6144                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6145                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6146                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6147                         }
6148                 }
6149                 break;
6150         }
6151
6152         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6153         {
6154                 r_bloomstate.enabled = true;
6155                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6156         }
6157
6158         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);
6159
6160         if (r_bloomstate.fbo_framebuffer)
6161                 r_refdef.view.clear = true;
6162 }
6163
6164 void R_Bloom_CopyBloomTexture(float colorscale)
6165 {
6166         r_refdef.stats.bloom++;
6167
6168         // scale down screen texture to the bloom texture size
6169         CHECKGLERROR
6170         R_Mesh_SetMainRenderTargets();
6171         R_SetViewport(&r_bloomstate.viewport);
6172         GL_BlendFunc(GL_ONE, GL_ZERO);
6173         GL_Color(colorscale, colorscale, colorscale, 1);
6174         // 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...
6175         switch(vid.renderpath)
6176         {
6177         case RENDERPATH_GL11:
6178         case RENDERPATH_GL13:
6179         case RENDERPATH_GL20:
6180         case RENDERPATH_GLES1:
6181         case RENDERPATH_GLES2:
6182         case RENDERPATH_SOFT:
6183                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6184                 break;
6185         case RENDERPATH_D3D9:
6186         case RENDERPATH_D3D10:
6187         case RENDERPATH_D3D11:
6188                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6189                 break;
6190         }
6191         // TODO: do boxfilter scale-down in shader?
6192         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6193         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6194         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6195
6196         // we now have a bloom image in the framebuffer
6197         // copy it into the bloom image texture for later processing
6198         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);
6199         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6200 }
6201
6202 void R_Bloom_CopyHDRTexture(void)
6203 {
6204         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);
6205         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6206 }
6207
6208 void R_Bloom_MakeTexture(void)
6209 {
6210         int x, range, dir;
6211         float xoffset, yoffset, r, brighten;
6212
6213         r_refdef.stats.bloom++;
6214
6215         R_ResetViewRendering2D();
6216
6217         // we have a bloom image in the framebuffer
6218         CHECKGLERROR
6219         R_SetViewport(&r_bloomstate.viewport);
6220
6221         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6222         {
6223                 x *= 2;
6224                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6225                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6226                 GL_Color(r,r,r,1);
6227                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6228                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6229                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6230                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6231
6232                 // copy the vertically blurred bloom view to a texture
6233                 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);
6234                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6235         }
6236
6237         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6238         brighten = r_bloom_brighten.value;
6239         if (r_bloomstate.hdr)
6240                 brighten *= r_hdr_range.value;
6241         brighten = sqrt(brighten);
6242         if(range >= 1)
6243                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6244         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6245
6246         for (dir = 0;dir < 2;dir++)
6247         {
6248                 // blend on at multiple vertical offsets to achieve a vertical blur
6249                 // TODO: do offset blends using GLSL
6250                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6251                 GL_BlendFunc(GL_ONE, GL_ZERO);
6252                 for (x = -range;x <= range;x++)
6253                 {
6254                         if (!dir){xoffset = 0;yoffset = x;}
6255                         else {xoffset = x;yoffset = 0;}
6256                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6257                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6258                         // compute a texcoord array with the specified x and y offset
6259                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6260                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6261                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6262                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6263                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6264                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6265                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6266                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6267                         // this r value looks like a 'dot' particle, fading sharply to
6268                         // black at the edges
6269                         // (probably not realistic but looks good enough)
6270                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6271                         //r = brighten/(range*2+1);
6272                         r = brighten / (range * 2 + 1);
6273                         if(range >= 1)
6274                                 r *= (1 - x*x/(float)(range*range));
6275                         GL_Color(r, r, r, 1);
6276                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6277                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6279                         GL_BlendFunc(GL_ONE, GL_ONE);
6280                 }
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
6288 void R_HDR_RenderBloomTexture(void)
6289 {
6290         int oldwidth, oldheight;
6291         float oldcolorscale;
6292         qboolean oldwaterstate;
6293
6294         oldwaterstate = r_waterstate.enabled;
6295         oldcolorscale = r_refdef.view.colorscale;
6296         oldwidth = r_refdef.view.width;
6297         oldheight = r_refdef.view.height;
6298         r_refdef.view.width = r_bloomstate.bloomwidth;
6299         r_refdef.view.height = r_bloomstate.bloomheight;
6300
6301         if(r_hdr.integer < 2)
6302                 r_waterstate.enabled = false;
6303
6304         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6305         // TODO: add exposure compensation features
6306         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6307
6308         r_refdef.view.showdebug = false;
6309         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6310
6311         R_ResetViewRendering3D();
6312
6313         R_ClearScreen(r_refdef.fogenabled);
6314         if (r_timereport_active)
6315                 R_TimeReport("HDRclear");
6316
6317         R_View_Update();
6318         if (r_timereport_active)
6319                 R_TimeReport("visibility");
6320
6321         // only do secondary renders with HDR if r_hdr is 2 or higher
6322         r_waterstate.numwaterplanes = 0;
6323         if (r_waterstate.enabled)
6324                 R_RenderWaterPlanes();
6325
6326         r_refdef.view.showdebug = true;
6327         R_RenderScene();
6328         r_waterstate.numwaterplanes = 0;
6329
6330         R_ResetViewRendering2D();
6331
6332         R_Bloom_CopyHDRTexture();
6333         R_Bloom_MakeTexture();
6334
6335         // restore the view settings
6336         r_waterstate.enabled = oldwaterstate;
6337         r_refdef.view.width = oldwidth;
6338         r_refdef.view.height = oldheight;
6339         r_refdef.view.colorscale = oldcolorscale;
6340
6341         R_ResetViewRendering3D();
6342
6343         R_ClearScreen(r_refdef.fogenabled);
6344         if (r_timereport_active)
6345                 R_TimeReport("viewclear");
6346 }
6347
6348 static void R_BlendView(void)
6349 {
6350         unsigned int permutation;
6351         float uservecs[4][4];
6352
6353         switch (vid.renderpath)
6354         {
6355         case RENDERPATH_GL20:
6356         case RENDERPATH_D3D9:
6357         case RENDERPATH_D3D10:
6358         case RENDERPATH_D3D11:
6359         case RENDERPATH_SOFT:
6360         case RENDERPATH_GLES2:
6361                 permutation =
6362                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6363                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6364                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6365                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6366                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6367
6368                 if (r_bloomstate.texture_screen)
6369                 {
6370                         // make sure the buffer is available
6371                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6372
6373                         R_ResetViewRendering2D();
6374                         R_Mesh_SetMainRenderTargets();
6375
6376                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6377                         {
6378                                 // declare variables
6379                                 float blur_factor, blur_mouseaccel, blur_velocity;
6380                                 static float blur_average; 
6381                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6382
6383                                 // set a goal for the factoring
6384                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6385                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6386                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6387                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6388                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6389                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6390
6391                                 // from the goal, pick an averaged value between goal and last value
6392                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6393                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6394                                 
6395                                 // enforce minimum amount of blur 
6396                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6397                                 
6398                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6399
6400                                 // calculate values into a standard alpha
6401                                 cl.motionbluralpha = 1 - exp(-
6402                                                 (
6403                                                  (r_motionblur.value * blur_factor / 80)
6404                                                  +
6405                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6406                                                 )
6407                                                 /
6408                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6409                                           );
6410                                 
6411                                 // randomization for the blur value to combat persistent ghosting
6412                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6413                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6414                                 
6415                                 // apply the blur
6416                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6417                                 {
6418                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6419                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6420                                         switch(vid.renderpath)
6421                                         {
6422                                         case RENDERPATH_GL11:
6423                                         case RENDERPATH_GL13:
6424                                         case RENDERPATH_GL20:
6425                                         case RENDERPATH_GLES1:
6426                                         case RENDERPATH_GLES2:
6427                                         case RENDERPATH_SOFT:
6428                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6429                                                 break;
6430                                         case RENDERPATH_D3D9:
6431                                         case RENDERPATH_D3D10:
6432                                         case RENDERPATH_D3D11:
6433                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6434                                                 break;
6435                                         }
6436                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6437                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6438                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6439                                 }
6440                                 
6441                                 // updates old view angles for next pass 
6442                                 VectorCopy(cl.viewangles, blur_oldangles);
6443                         }
6444
6445                         // copy view into the screen texture
6446                         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);
6447                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6448                 }
6449                 else if (!r_bloomstate.texture_bloom)
6450                 {
6451                         // we may still have to do view tint...
6452                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6453                         {
6454                                 // apply a color tint to the whole view
6455                                 R_ResetViewRendering2D();
6456                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6457                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6458                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6459                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6460                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6461                         }
6462                         break; // no screen processing, no bloom, skip it
6463                 }
6464
6465                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6466                 {
6467                         // render simple bloom effect
6468                         // copy the screen and shrink it and darken it for the bloom process
6469                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6470                         // make the bloom texture
6471                         R_Bloom_MakeTexture();
6472                 }
6473
6474 #if _MSC_VER >= 1400
6475 #define sscanf sscanf_s
6476 #endif
6477                 memset(uservecs, 0, sizeof(uservecs));
6478                 if (r_glsl_postprocess_uservec1_enable.integer)
6479                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6480                 if (r_glsl_postprocess_uservec2_enable.integer)
6481                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6482                 if (r_glsl_postprocess_uservec3_enable.integer)
6483                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6484                 if (r_glsl_postprocess_uservec4_enable.integer)
6485                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6486
6487                 R_ResetViewRendering2D();
6488                 GL_Color(1, 1, 1, 1);
6489                 GL_BlendFunc(GL_ONE, GL_ZERO);
6490
6491                 switch(vid.renderpath)
6492                 {
6493                 case RENDERPATH_GL20:
6494                 case RENDERPATH_GLES2:
6495                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6496                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6497                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6498                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6499                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6500                         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]);
6501                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6502                         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]);
6503                         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]);
6504                         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]);
6505                         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]);
6506                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6507                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6508                         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);
6509                         break;
6510                 case RENDERPATH_D3D9:
6511 #ifdef SUPPORTD3D
6512                         // 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...
6513                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6514                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6515                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6516                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6517                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6518                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6519                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6520                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6521                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6522                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6523                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6524                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6525                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6526                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6527 #endif
6528                         break;
6529                 case RENDERPATH_D3D10:
6530                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6531                         break;
6532                 case RENDERPATH_D3D11:
6533                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6534                         break;
6535                 case RENDERPATH_SOFT:
6536                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6537                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6538                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6539                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6540                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6541                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6542                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6543                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6544                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6545                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6546                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6547                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6548                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6549                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6550                         break;
6551                 default:
6552                         break;
6553                 }
6554                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6555                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6556                 break;
6557         case RENDERPATH_GL11:
6558         case RENDERPATH_GL13:
6559         case RENDERPATH_GLES1:
6560                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6561                 {
6562                         // apply a color tint to the whole view
6563                         R_ResetViewRendering2D();
6564                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6565                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6566                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6567                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6568                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6569                 }
6570                 break;
6571         }
6572 }
6573
6574 matrix4x4_t r_waterscrollmatrix;
6575
6576 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6577 {
6578         // Nehahra fog
6579         if (gamemode == GAME_NEHAHRA)
6580         {
6581                 if (gl_fogenable.integer)
6582                 {
6583                         r_refdef.oldgl_fogenable = true;
6584                         r_refdef.fog_density = gl_fogdensity.value;
6585                         r_refdef.fog_red = gl_fogred.value;
6586                         r_refdef.fog_green = gl_foggreen.value;
6587                         r_refdef.fog_blue = gl_fogblue.value;
6588                         r_refdef.fog_alpha = 1;
6589                         r_refdef.fog_start = 0;
6590                         r_refdef.fog_end = gl_skyclip.value;
6591                         r_refdef.fog_height = 1<<30;
6592                         r_refdef.fog_fadedepth = 128;
6593                 }
6594                 else if (r_refdef.oldgl_fogenable)
6595                 {
6596                         r_refdef.oldgl_fogenable = false;
6597                         r_refdef.fog_density = 0;
6598                         r_refdef.fog_red = 0;
6599                         r_refdef.fog_green = 0;
6600                         r_refdef.fog_blue = 0;
6601                         r_refdef.fog_alpha = 0;
6602                         r_refdef.fog_start = 0;
6603                         r_refdef.fog_end = 0;
6604                         r_refdef.fog_height = 1<<30;
6605                         r_refdef.fog_fadedepth = 128;
6606                 }
6607         }
6608
6609         // fog parms
6610         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6611         r_refdef.fog_start = max(0, r_refdef.fog_start);
6612         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6613
6614         if (r_refdef.fog_density && r_drawfog.integer)
6615         {
6616                 r_refdef.fogenabled = true;
6617                 // this is the point where the fog reaches 0.9986 alpha, which we
6618                 // consider a good enough cutoff point for the texture
6619                 // (0.9986 * 256 == 255.6)
6620                 if (r_fog_exp2.integer)
6621                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6622                 else
6623                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6624                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6625                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6626                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6627                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6628                         R_BuildFogHeightTexture();
6629                 // fog color was already set
6630                 // update the fog texture
6631                 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)
6632                         R_BuildFogTexture();
6633                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6634                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6635         }
6636         else
6637                 r_refdef.fogenabled = false;
6638
6639         // fog color
6640         if (r_refdef.fog_density)
6641         {
6642                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6643                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6644                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6645
6646                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6647                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6648                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6649                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6650
6651                 {
6652                         vec3_t fogvec;
6653                         VectorCopy(r_refdef.fogcolor, fogvec);
6654                         //   color.rgb *= ContrastBoost * SceneBrightness;
6655                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6656                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6657                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6658                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6659                 }
6660         }
6661 }
6662
6663 void R_UpdateVariables(void)
6664 {
6665         R_Textures_Frame();
6666
6667         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6668
6669         r_refdef.farclip = r_farclip_base.value;
6670         if (r_refdef.scene.worldmodel)
6671                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6672         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6673
6674         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6675                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6676         r_refdef.polygonfactor = 0;
6677         r_refdef.polygonoffset = 0;
6678         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6679         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6680
6681         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6682         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6683         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6684         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6685         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6686         if (FAKELIGHT_ENABLED)
6687         {
6688                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6689         }
6690         if (r_showsurfaces.integer)
6691         {
6692                 r_refdef.scene.rtworld = false;
6693                 r_refdef.scene.rtworldshadows = false;
6694                 r_refdef.scene.rtdlight = false;
6695                 r_refdef.scene.rtdlightshadows = false;
6696                 r_refdef.lightmapintensity = 0;
6697         }
6698
6699         switch(vid.renderpath)
6700         {
6701         case RENDERPATH_GL20:
6702         case RENDERPATH_D3D9:
6703         case RENDERPATH_D3D10:
6704         case RENDERPATH_D3D11:
6705         case RENDERPATH_SOFT:
6706         case RENDERPATH_GLES2:
6707                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6708                 {
6709                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6710                         {
6711                                 // build GLSL gamma texture
6712 #define RAMPWIDTH 256
6713                                 unsigned short ramp[RAMPWIDTH * 3];
6714                                 unsigned char rampbgr[RAMPWIDTH][4];
6715                                 int i;
6716
6717                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6718
6719                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6720                                 for(i = 0; i < RAMPWIDTH; ++i)
6721                                 {
6722                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6723                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6724                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6725                                         rampbgr[i][3] = 0;
6726                                 }
6727                                 if (r_texture_gammaramps)
6728                                 {
6729                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6730                                 }
6731                                 else
6732                                 {
6733                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6734                                 }
6735                         }
6736                 }
6737                 else
6738                 {
6739                         // remove GLSL gamma texture
6740                 }
6741                 break;
6742         case RENDERPATH_GL11:
6743         case RENDERPATH_GL13:
6744         case RENDERPATH_GLES1:
6745                 break;
6746         }
6747 }
6748
6749 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6750 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6751 /*
6752 ================
6753 R_SelectScene
6754 ================
6755 */
6756 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6757         if( scenetype != r_currentscenetype ) {
6758                 // store the old scenetype
6759                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6760                 r_currentscenetype = scenetype;
6761                 // move in the new scene
6762                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6763         }
6764 }
6765
6766 /*
6767 ================
6768 R_GetScenePointer
6769 ================
6770 */
6771 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6772 {
6773         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6774         if( scenetype == r_currentscenetype ) {
6775                 return &r_refdef.scene;
6776         } else {
6777                 return &r_scenes_store[ scenetype ];
6778         }
6779 }
6780
6781 int R_SortEntities_Compare(const void *ap, const void *bp)
6782 {
6783         const entity_render_t *a = *(const entity_render_t **)ap;
6784         const entity_render_t *b = *(const entity_render_t **)bp;
6785
6786         // 1. compare model
6787         if(a->model < b->model)
6788                 return -1;
6789         if(a->model > b->model)
6790                 return +1;
6791
6792         // 2. compare skin
6793         // TODO possibly calculate the REAL skinnum here first using
6794         // skinscenes?
6795         if(a->skinnum < b->skinnum)
6796                 return -1;
6797         if(a->skinnum > b->skinnum)
6798                 return +1;
6799
6800         // everything we compared is equal
6801         return 0;
6802 }
6803 void R_SortEntities(void)
6804 {
6805         // below or equal 2 ents, sorting never gains anything
6806         if(r_refdef.scene.numentities <= 2)
6807                 return;
6808         // sort
6809         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6810 }
6811
6812 /*
6813 ================
6814 R_RenderView
6815 ================
6816 */
6817 int dpsoftrast_test;
6818 extern void R_Shadow_UpdateBounceGridTexture(void);
6819 extern cvar_t r_shadow_bouncegrid;
6820 void R_RenderView(void)
6821 {
6822         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6823
6824         dpsoftrast_test = r_test.integer;
6825
6826         if (r_timereport_active)
6827                 R_TimeReport("start");
6828         r_textureframe++; // used only by R_GetCurrentTexture
6829         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6830
6831         if(R_CompileShader_CheckStaticParms())
6832                 R_GLSL_Restart_f();
6833
6834         if (!r_drawentities.integer)
6835                 r_refdef.scene.numentities = 0;
6836         else if (r_sortentities.integer)
6837                 R_SortEntities();
6838
6839         R_AnimCache_ClearCache();
6840         R_FrameData_NewFrame();
6841
6842         /* adjust for stereo display */
6843         if(R_Stereo_Active())
6844         {
6845                 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);
6846                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6847         }
6848
6849         if (r_refdef.view.isoverlay)
6850         {
6851                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6852                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6853                 R_TimeReport("depthclear");
6854
6855                 r_refdef.view.showdebug = false;
6856
6857                 r_waterstate.enabled = false;
6858                 r_waterstate.numwaterplanes = 0;
6859
6860                 R_RenderScene();
6861
6862                 r_refdef.view.matrix = originalmatrix;
6863
6864                 CHECKGLERROR
6865                 return;
6866         }
6867
6868         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6869         {
6870                 r_refdef.view.matrix = originalmatrix;
6871                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6872         }
6873
6874         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6875
6876         R_RenderView_UpdateViewVectors();
6877
6878         R_Shadow_UpdateWorldLightSelection();
6879
6880         R_Bloom_StartFrame();
6881         R_Water_StartFrame();
6882
6883         CHECKGLERROR
6884         if (r_timereport_active)
6885                 R_TimeReport("viewsetup");
6886
6887         R_ResetViewRendering3D();
6888
6889         if (r_refdef.view.clear || r_refdef.fogenabled)
6890         {
6891                 R_ClearScreen(r_refdef.fogenabled);
6892                 if (r_timereport_active)
6893                         R_TimeReport("viewclear");
6894         }
6895         r_refdef.view.clear = true;
6896
6897         // this produces a bloom texture to be used in R_BlendView() later
6898         if (r_bloomstate.hdr)
6899         {
6900                 R_HDR_RenderBloomTexture();
6901                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6902                 r_textureframe++; // used only by R_GetCurrentTexture
6903         }
6904
6905         r_refdef.view.showdebug = true;
6906
6907         R_View_Update();
6908         if (r_timereport_active)
6909                 R_TimeReport("visibility");
6910
6911         R_Shadow_UpdateBounceGridTexture();
6912         if (r_timereport_active && r_shadow_bouncegrid.integer)
6913                 R_TimeReport("bouncegrid");
6914
6915         r_waterstate.numwaterplanes = 0;
6916         if (r_waterstate.enabled)
6917                 R_RenderWaterPlanes();
6918
6919         R_RenderScene();
6920         r_waterstate.numwaterplanes = 0;
6921
6922         R_BlendView();
6923         if (r_timereport_active)
6924                 R_TimeReport("blendview");
6925
6926         GL_Scissor(0, 0, vid.width, vid.height);
6927         GL_ScissorTest(false);
6928
6929         r_refdef.view.matrix = originalmatrix;
6930
6931         CHECKGLERROR
6932 }
6933
6934 void R_RenderWaterPlanes(void)
6935 {
6936         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6937         {
6938                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6939                 if (r_timereport_active)
6940                         R_TimeReport("waterworld");
6941         }
6942
6943         // don't let sound skip if going slow
6944         if (r_refdef.scene.extraupdate)
6945                 S_ExtraUpdate ();
6946
6947         R_DrawModelsAddWaterPlanes();
6948         if (r_timereport_active)
6949                 R_TimeReport("watermodels");
6950
6951         if (r_waterstate.numwaterplanes)
6952         {
6953                 R_Water_ProcessPlanes();
6954                 if (r_timereport_active)
6955                         R_TimeReport("waterscenes");
6956         }
6957 }
6958
6959 extern void R_DrawLightningBeams (void);
6960 extern void VM_CL_AddPolygonsToMeshQueue (void);
6961 extern void R_DrawPortals (void);
6962 extern cvar_t cl_locs_show;
6963 static void R_DrawLocs(void);
6964 static void R_DrawEntityBBoxes(void);
6965 static void R_DrawModelDecals(void);
6966 extern void R_DrawModelShadows(void);
6967 extern void R_DrawModelShadowMaps(void);
6968 extern cvar_t cl_decals_newsystem;
6969 extern qboolean r_shadow_usingdeferredprepass;
6970 void R_RenderScene(void)
6971 {
6972         qboolean shadowmapping = false;
6973
6974         if (r_timereport_active)
6975                 R_TimeReport("beginscene");
6976
6977         r_refdef.stats.renders++;
6978
6979         R_UpdateFog();
6980
6981         // don't let sound skip if going slow
6982         if (r_refdef.scene.extraupdate)
6983                 S_ExtraUpdate ();
6984
6985         R_MeshQueue_BeginScene();
6986
6987         R_SkyStartFrame();
6988
6989         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);
6990
6991         if (r_timereport_active)
6992                 R_TimeReport("skystartframe");
6993
6994         if (cl.csqc_vidvars.drawworld)
6995         {
6996                 // don't let sound skip if going slow
6997                 if (r_refdef.scene.extraupdate)
6998                         S_ExtraUpdate ();
6999
7000                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7001                 {
7002                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7003                         if (r_timereport_active)
7004                                 R_TimeReport("worldsky");
7005                 }
7006
7007                 if (R_DrawBrushModelsSky() && r_timereport_active)
7008                         R_TimeReport("bmodelsky");
7009
7010                 if (skyrendermasked && skyrenderlater)
7011                 {
7012                         // we have to force off the water clipping plane while rendering sky
7013                         R_SetupView(false);
7014                         R_Sky();
7015                         R_SetupView(true);
7016                         if (r_timereport_active)
7017                                 R_TimeReport("sky");
7018                 }
7019         }
7020
7021         R_AnimCache_CacheVisibleEntities();
7022         if (r_timereport_active)
7023                 R_TimeReport("animation");
7024
7025         R_Shadow_PrepareLights();
7026         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7027                 R_Shadow_PrepareModelShadows();
7028         if (r_timereport_active)
7029                 R_TimeReport("preparelights");
7030
7031         if (R_Shadow_ShadowMappingEnabled())
7032                 shadowmapping = true;
7033
7034         if (r_shadow_usingdeferredprepass)
7035                 R_Shadow_DrawPrepass();
7036
7037         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7038         {
7039                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7040                 if (r_timereport_active)
7041                         R_TimeReport("worlddepth");
7042         }
7043         if (r_depthfirst.integer >= 2)
7044         {
7045                 R_DrawModelsDepth();
7046                 if (r_timereport_active)
7047                         R_TimeReport("modeldepth");
7048         }
7049
7050         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7051         {
7052                 R_DrawModelShadowMaps();
7053                 R_ResetViewRendering3D();
7054                 // don't let sound skip if going slow
7055                 if (r_refdef.scene.extraupdate)
7056                         S_ExtraUpdate ();
7057         }
7058
7059         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7060         {
7061                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7062                 if (r_timereport_active)
7063                         R_TimeReport("world");
7064         }
7065
7066         // don't let sound skip if going slow
7067         if (r_refdef.scene.extraupdate)
7068                 S_ExtraUpdate ();
7069
7070         R_DrawModels();
7071         if (r_timereport_active)
7072                 R_TimeReport("models");
7073
7074         // don't let sound skip if going slow
7075         if (r_refdef.scene.extraupdate)
7076                 S_ExtraUpdate ();
7077
7078         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7079         {
7080                 R_DrawModelShadows();
7081                 R_ResetViewRendering3D();
7082                 // don't let sound skip if going slow
7083                 if (r_refdef.scene.extraupdate)
7084                         S_ExtraUpdate ();
7085         }
7086
7087         if (!r_shadow_usingdeferredprepass)
7088         {
7089                 R_Shadow_DrawLights();
7090                 if (r_timereport_active)
7091                         R_TimeReport("rtlights");
7092         }
7093
7094         // don't let sound skip if going slow
7095         if (r_refdef.scene.extraupdate)
7096                 S_ExtraUpdate ();
7097
7098         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7099         {
7100                 R_DrawModelShadows();
7101                 R_ResetViewRendering3D();
7102                 // don't let sound skip if going slow
7103                 if (r_refdef.scene.extraupdate)
7104                         S_ExtraUpdate ();
7105         }
7106
7107         if (cl.csqc_vidvars.drawworld)
7108         {
7109                 if (cl_decals_newsystem.integer)
7110                 {
7111                         R_DrawModelDecals();
7112                         if (r_timereport_active)
7113                                 R_TimeReport("modeldecals");
7114                 }
7115                 else
7116                 {
7117                         R_DrawDecals();
7118                         if (r_timereport_active)
7119                                 R_TimeReport("decals");
7120                 }
7121
7122                 R_DrawParticles();
7123                 if (r_timereport_active)
7124                         R_TimeReport("particles");
7125
7126                 R_DrawExplosions();
7127                 if (r_timereport_active)
7128                         R_TimeReport("explosions");
7129
7130                 R_DrawLightningBeams();
7131                 if (r_timereport_active)
7132                         R_TimeReport("lightning");
7133         }
7134
7135         VM_CL_AddPolygonsToMeshQueue();
7136
7137         if (r_refdef.view.showdebug)
7138         {
7139                 if (cl_locs_show.integer)
7140                 {
7141                         R_DrawLocs();
7142                         if (r_timereport_active)
7143                                 R_TimeReport("showlocs");
7144                 }
7145
7146                 if (r_drawportals.integer)
7147                 {
7148                         R_DrawPortals();
7149                         if (r_timereport_active)
7150                                 R_TimeReport("portals");
7151                 }
7152
7153                 if (r_showbboxes.value > 0)
7154                 {
7155                         R_DrawEntityBBoxes();
7156                         if (r_timereport_active)
7157                                 R_TimeReport("bboxes");
7158                 }
7159         }
7160
7161         if (r_transparent.integer)
7162         {
7163                 R_MeshQueue_RenderTransparent();
7164                 if (r_timereport_active)
7165                         R_TimeReport("drawtrans");
7166         }
7167
7168         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))
7169         {
7170                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7171                 if (r_timereport_active)
7172                         R_TimeReport("worlddebug");
7173                 R_DrawModelsDebug();
7174                 if (r_timereport_active)
7175                         R_TimeReport("modeldebug");
7176         }
7177
7178         if (cl.csqc_vidvars.drawworld)
7179         {
7180                 R_Shadow_DrawCoronas();
7181                 if (r_timereport_active)
7182                         R_TimeReport("coronas");
7183         }
7184
7185 #if 0
7186         {
7187                 GL_DepthTest(false);
7188                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7189                 GL_Color(1, 1, 1, 1);
7190                 qglBegin(GL_POLYGON);
7191                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7192                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7193                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7194                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7195                 qglEnd();
7196                 qglBegin(GL_POLYGON);
7197                 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]);
7198                 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]);
7199                 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]);
7200                 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]);
7201                 qglEnd();
7202                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7203         }
7204 #endif
7205
7206         // don't let sound skip if going slow
7207         if (r_refdef.scene.extraupdate)
7208                 S_ExtraUpdate ();
7209
7210         R_ResetViewRendering2D();
7211 }
7212
7213 static const unsigned short bboxelements[36] =
7214 {
7215         5, 1, 3, 5, 3, 7,
7216         6, 2, 0, 6, 0, 4,
7217         7, 3, 2, 7, 2, 6,
7218         4, 0, 1, 4, 1, 5,
7219         4, 5, 7, 4, 7, 6,
7220         1, 0, 2, 1, 2, 3,
7221 };
7222
7223 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7224 {
7225         int i;
7226         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7227
7228         RSurf_ActiveWorldEntity();
7229
7230         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7231         GL_DepthMask(false);
7232         GL_DepthRange(0, 1);
7233         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7234 //      R_Mesh_ResetTextureState();
7235
7236         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7237         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7238         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7239         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7240         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7241         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7242         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7243         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7244         R_FillColors(color4f, 8, cr, cg, cb, ca);
7245         if (r_refdef.fogenabled)
7246         {
7247                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7248                 {
7249                         f1 = RSurf_FogVertex(v);
7250                         f2 = 1 - f1;
7251                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7252                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7253                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7254                 }
7255         }
7256         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7257         R_Mesh_ResetTextureState();
7258         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7259         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7260 }
7261
7262 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7263 {
7264         int i;
7265         float color[4];
7266         prvm_edict_t *edict;
7267         prvm_prog_t *prog_save = prog;
7268
7269         // this function draws bounding boxes of server entities
7270         if (!sv.active)
7271                 return;
7272
7273         GL_CullFace(GL_NONE);
7274         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7275
7276         prog = 0;
7277         SV_VM_Begin();
7278         for (i = 0;i < numsurfaces;i++)
7279         {
7280                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7281                 switch ((int)PRVM_serveredictfloat(edict, solid))
7282                 {
7283                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7284                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7285                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7286                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7287                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7288                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7289                 }
7290                 color[3] *= r_showbboxes.value;
7291                 color[3] = bound(0, color[3], 1);
7292                 GL_DepthTest(!r_showdisabledepthtest.integer);
7293                 GL_CullFace(r_refdef.view.cullface_front);
7294                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7295         }
7296         SV_VM_End();
7297         prog = prog_save;
7298 }
7299
7300 static void R_DrawEntityBBoxes(void)
7301 {
7302         int i;
7303         prvm_edict_t *edict;
7304         vec3_t center;
7305         prvm_prog_t *prog_save = prog;
7306
7307         // this function draws bounding boxes of server entities
7308         if (!sv.active)
7309                 return;
7310
7311         prog = 0;
7312         SV_VM_Begin();
7313         for (i = 0;i < prog->num_edicts;i++)
7314         {
7315                 edict = PRVM_EDICT_NUM(i);
7316                 if (edict->priv.server->free)
7317                         continue;
7318                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7319                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7320                         continue;
7321                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7322                         continue;
7323                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7324                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7325         }
7326         SV_VM_End();
7327         prog = prog_save;
7328 }
7329
7330 static const int nomodelelement3i[24] =
7331 {
7332         5, 2, 0,
7333         5, 1, 2,
7334         5, 0, 3,
7335         5, 3, 1,
7336         0, 2, 4,
7337         2, 1, 4,
7338         3, 0, 4,
7339         1, 3, 4
7340 };
7341
7342 static const unsigned short nomodelelement3s[24] =
7343 {
7344         5, 2, 0,
7345         5, 1, 2,
7346         5, 0, 3,
7347         5, 3, 1,
7348         0, 2, 4,
7349         2, 1, 4,
7350         3, 0, 4,
7351         1, 3, 4
7352 };
7353
7354 static const float nomodelvertex3f[6*3] =
7355 {
7356         -16,   0,   0,
7357          16,   0,   0,
7358           0, -16,   0,
7359           0,  16,   0,
7360           0,   0, -16,
7361           0,   0,  16
7362 };
7363
7364 static const float nomodelcolor4f[6*4] =
7365 {
7366         0.0f, 0.0f, 0.5f, 1.0f,
7367         0.0f, 0.0f, 0.5f, 1.0f,
7368         0.0f, 0.5f, 0.0f, 1.0f,
7369         0.0f, 0.5f, 0.0f, 1.0f,
7370         0.5f, 0.0f, 0.0f, 1.0f,
7371         0.5f, 0.0f, 0.0f, 1.0f
7372 };
7373
7374 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7375 {
7376         int i;
7377         float f1, f2, *c;
7378         float color4f[6*4];
7379
7380         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);
7381
7382         // this is only called once per entity so numsurfaces is always 1, and
7383         // surfacelist is always {0}, so this code does not handle batches
7384
7385         if (rsurface.ent_flags & RENDER_ADDITIVE)
7386         {
7387                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7388                 GL_DepthMask(false);
7389         }
7390         else if (rsurface.colormod[3] < 1)
7391         {
7392                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7393                 GL_DepthMask(false);
7394         }
7395         else
7396         {
7397                 GL_BlendFunc(GL_ONE, GL_ZERO);
7398                 GL_DepthMask(true);
7399         }
7400         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7401         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7402         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7403         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7404         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7405         for (i = 0, c = color4f;i < 6;i++, c += 4)
7406         {
7407                 c[0] *= rsurface.colormod[0];
7408                 c[1] *= rsurface.colormod[1];
7409                 c[2] *= rsurface.colormod[2];
7410                 c[3] *= rsurface.colormod[3];
7411         }
7412         if (r_refdef.fogenabled)
7413         {
7414                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7415                 {
7416                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7417                         f2 = 1 - f1;
7418                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7419                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7420                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7421                 }
7422         }
7423 //      R_Mesh_ResetTextureState();
7424         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7425         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7426         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7427 }
7428
7429 void R_DrawNoModel(entity_render_t *ent)
7430 {
7431         vec3_t org;
7432         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7433         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7434                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7435         else
7436                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7437 }
7438
7439 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7440 {
7441         vec3_t right1, right2, diff, normal;
7442
7443         VectorSubtract (org2, org1, normal);
7444
7445         // calculate 'right' vector for start
7446         VectorSubtract (r_refdef.view.origin, org1, diff);
7447         CrossProduct (normal, diff, right1);
7448         VectorNormalize (right1);
7449
7450         // calculate 'right' vector for end
7451         VectorSubtract (r_refdef.view.origin, org2, diff);
7452         CrossProduct (normal, diff, right2);
7453         VectorNormalize (right2);
7454
7455         vert[ 0] = org1[0] + width * right1[0];
7456         vert[ 1] = org1[1] + width * right1[1];
7457         vert[ 2] = org1[2] + width * right1[2];
7458         vert[ 3] = org1[0] - width * right1[0];
7459         vert[ 4] = org1[1] - width * right1[1];
7460         vert[ 5] = org1[2] - width * right1[2];
7461         vert[ 6] = org2[0] - width * right2[0];
7462         vert[ 7] = org2[1] - width * right2[1];
7463         vert[ 8] = org2[2] - width * right2[2];
7464         vert[ 9] = org2[0] + width * right2[0];
7465         vert[10] = org2[1] + width * right2[1];
7466         vert[11] = org2[2] + width * right2[2];
7467 }
7468
7469 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)
7470 {
7471         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7472         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7473         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7474         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7475         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7476         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7477         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7478         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7479         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7480         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7481         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7482         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7483 }
7484
7485 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7486 {
7487         int i;
7488         float *vertex3f;
7489         float v[3];
7490         VectorSet(v, x, y, z);
7491         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7492                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7493                         break;
7494         if (i == mesh->numvertices)
7495         {
7496                 if (mesh->numvertices < mesh->maxvertices)
7497                 {
7498                         VectorCopy(v, vertex3f);
7499                         mesh->numvertices++;
7500                 }
7501                 return mesh->numvertices;
7502         }
7503         else
7504                 return i;
7505 }
7506
7507 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7508 {
7509         int i;
7510         int *e, element[3];
7511         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7512         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7513         e = mesh->element3i + mesh->numtriangles * 3;
7514         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7515         {
7516                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7517                 if (mesh->numtriangles < mesh->maxtriangles)
7518                 {
7519                         *e++ = element[0];
7520                         *e++ = element[1];
7521                         *e++ = element[2];
7522                         mesh->numtriangles++;
7523                 }
7524                 element[1] = element[2];
7525         }
7526 }
7527
7528 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7529 {
7530         int i;
7531         int *e, element[3];
7532         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7533         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7534         e = mesh->element3i + mesh->numtriangles * 3;
7535         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7536         {
7537                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7538                 if (mesh->numtriangles < mesh->maxtriangles)
7539                 {
7540                         *e++ = element[0];
7541                         *e++ = element[1];
7542                         *e++ = element[2];
7543                         mesh->numtriangles++;
7544                 }
7545                 element[1] = element[2];
7546         }
7547 }
7548
7549 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7550 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7551 {
7552         int planenum, planenum2;
7553         int w;
7554         int tempnumpoints;
7555         mplane_t *plane, *plane2;
7556         double maxdist;
7557         double temppoints[2][256*3];
7558         // figure out how large a bounding box we need to properly compute this brush
7559         maxdist = 0;
7560         for (w = 0;w < numplanes;w++)
7561                 maxdist = max(maxdist, fabs(planes[w].dist));
7562         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7563         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7564         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7565         {
7566                 w = 0;
7567                 tempnumpoints = 4;
7568                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7569                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7570                 {
7571                         if (planenum2 == planenum)
7572                                 continue;
7573                         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);
7574                         w = !w;
7575                 }
7576                 if (tempnumpoints < 3)
7577                         continue;
7578                 // generate elements forming a triangle fan for this polygon
7579                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7580         }
7581 }
7582
7583 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)
7584 {
7585         texturelayer_t *layer;
7586         layer = t->currentlayers + t->currentnumlayers++;
7587         layer->type = type;
7588         layer->depthmask = depthmask;
7589         layer->blendfunc1 = blendfunc1;
7590         layer->blendfunc2 = blendfunc2;
7591         layer->texture = texture;
7592         layer->texmatrix = *matrix;
7593         layer->color[0] = r;
7594         layer->color[1] = g;
7595         layer->color[2] = b;
7596         layer->color[3] = a;
7597 }
7598
7599 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7600 {
7601         if(parms[0] == 0 && parms[1] == 0)
7602                 return false;
7603         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7604                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7605                         return false;
7606         return true;
7607 }
7608
7609 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7610 {
7611         double index, f;
7612         index = parms[2] + rsurface.shadertime * parms[3];
7613         index -= floor(index);
7614         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7615         {
7616         default:
7617         case Q3WAVEFUNC_NONE:
7618         case Q3WAVEFUNC_NOISE:
7619         case Q3WAVEFUNC_COUNT:
7620                 f = 0;
7621                 break;
7622         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7623         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7624         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7625         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7626         case Q3WAVEFUNC_TRIANGLE:
7627                 index *= 4;
7628                 f = index - floor(index);
7629                 if (index < 1)
7630                 {
7631                         // f = f;
7632                 }
7633                 else if (index < 2)
7634                         f = 1 - f;
7635                 else if (index < 3)
7636                         f = -f;
7637                 else
7638                         f = -(1 - f);
7639                 break;
7640         }
7641         f = parms[0] + parms[1] * f;
7642         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7643                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7644         return (float) f;
7645 }
7646
7647 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7648 {
7649         int w, h, idx;
7650         double f;
7651         double offsetd[2];
7652         float tcmat[12];
7653         matrix4x4_t matrix, temp;
7654         switch(tcmod->tcmod)
7655         {
7656                 case Q3TCMOD_COUNT:
7657                 case Q3TCMOD_NONE:
7658                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7659                                 matrix = r_waterscrollmatrix;
7660                         else
7661                                 matrix = identitymatrix;
7662                         break;
7663                 case Q3TCMOD_ENTITYTRANSLATE:
7664                         // this is used in Q3 to allow the gamecode to control texcoord
7665                         // scrolling on the entity, which is not supported in darkplaces yet.
7666                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7667                         break;
7668                 case Q3TCMOD_ROTATE:
7669                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7670                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7671                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7672                         break;
7673                 case Q3TCMOD_SCALE:
7674                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7675                         break;
7676                 case Q3TCMOD_SCROLL:
7677                         // extra care is needed because of precision breakdown with large values of time
7678                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7679                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7680                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7681                         break;
7682                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7683                         w = (int) tcmod->parms[0];
7684                         h = (int) tcmod->parms[1];
7685                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7686                         f = f - floor(f);
7687                         idx = (int) floor(f * w * h);
7688                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7689                         break;
7690                 case Q3TCMOD_STRETCH:
7691                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7692                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7693                         break;
7694                 case Q3TCMOD_TRANSFORM:
7695                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7696                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7697                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7698                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7699                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7700                         break;
7701                 case Q3TCMOD_TURBULENT:
7702                         // this is handled in the RSurf_PrepareVertices function
7703                         matrix = identitymatrix;
7704                         break;
7705         }
7706         temp = *texmatrix;
7707         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7708 }
7709
7710 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7711 {
7712         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7713         char name[MAX_QPATH];
7714         skinframe_t *skinframe;
7715         unsigned char pixels[296*194];
7716         strlcpy(cache->name, skinname, sizeof(cache->name));
7717         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7718         if (developer_loading.integer)
7719                 Con_Printf("loading %s\n", name);
7720         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7721         if (!skinframe || !skinframe->base)
7722         {
7723                 unsigned char *f;
7724                 fs_offset_t filesize;
7725                 skinframe = NULL;
7726                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7727                 if (f)
7728                 {
7729                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7730                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7731                         Mem_Free(f);
7732                 }
7733         }
7734         cache->skinframe = skinframe;
7735 }
7736
7737 texture_t *R_GetCurrentTexture(texture_t *t)
7738 {
7739         int i;
7740         const entity_render_t *ent = rsurface.entity;
7741         dp_model_t *model = ent->model;
7742         q3shaderinfo_layer_tcmod_t *tcmod;
7743
7744         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7745                 return t->currentframe;
7746         t->update_lastrenderframe = r_textureframe;
7747         t->update_lastrenderentity = (void *)ent;
7748
7749         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7750                 t->camera_entity = ent->entitynumber;
7751         else
7752                 t->camera_entity = 0;
7753
7754         // switch to an alternate material if this is a q1bsp animated material
7755         {
7756                 texture_t *texture = t;
7757                 int s = rsurface.ent_skinnum;
7758                 if ((unsigned int)s >= (unsigned int)model->numskins)
7759                         s = 0;
7760                 if (model->skinscenes)
7761                 {
7762                         if (model->skinscenes[s].framecount > 1)
7763                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7764                         else
7765                                 s = model->skinscenes[s].firstframe;
7766                 }
7767                 if (s > 0)
7768                         t = t + s * model->num_surfaces;
7769                 if (t->animated)
7770                 {
7771                         // use an alternate animation if the entity's frame is not 0,
7772                         // and only if the texture has an alternate animation
7773                         if (rsurface.ent_alttextures && t->anim_total[1])
7774                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7775                         else
7776                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7777                 }
7778                 texture->currentframe = t;
7779         }
7780
7781         // update currentskinframe to be a qw skin or animation frame
7782         if (rsurface.ent_qwskin >= 0)
7783         {
7784                 i = rsurface.ent_qwskin;
7785                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7786                 {
7787                         r_qwskincache_size = cl.maxclients;
7788                         if (r_qwskincache)
7789                                 Mem_Free(r_qwskincache);
7790                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7791                 }
7792                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7793                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7794                 t->currentskinframe = r_qwskincache[i].skinframe;
7795                 if (t->currentskinframe == NULL)
7796                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7797         }
7798         else if (t->numskinframes >= 2)
7799                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7800         if (t->backgroundnumskinframes >= 2)
7801                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7802
7803         t->currentmaterialflags = t->basematerialflags;
7804         t->currentalpha = rsurface.colormod[3];
7805         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7806                 t->currentalpha *= r_wateralpha.value;
7807         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7808                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7809         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7810                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7811         if (!(rsurface.ent_flags & RENDER_LIGHT))
7812                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7813         else if (FAKELIGHT_ENABLED)
7814         {
7815                 // no modellight if using fakelight for the map
7816         }
7817         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7818         {
7819                 // pick a model lighting mode
7820                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7821                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7822                 else
7823                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7824         }
7825         if (rsurface.ent_flags & RENDER_ADDITIVE)
7826                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7827         else if (t->currentalpha < 1)
7828                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7829         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7830                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7831         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7832                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7833         if (t->backgroundnumskinframes)
7834                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7835         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7836         {
7837                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7838                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7839         }
7840         else
7841                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7842         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7843         {
7844                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7845                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7846         }
7847         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7848                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7849
7850         // there is no tcmod
7851         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7852         {
7853                 t->currenttexmatrix = r_waterscrollmatrix;
7854                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7855         }
7856         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7857         {
7858                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7859                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7860         }
7861
7862         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7863                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7864         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7865                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7866
7867         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7868         if (t->currentskinframe->qpixels)
7869                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7870         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7871         if (!t->basetexture)
7872                 t->basetexture = r_texture_notexture;
7873         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7874         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7875         t->nmaptexture = t->currentskinframe->nmap;
7876         if (!t->nmaptexture)
7877                 t->nmaptexture = r_texture_blanknormalmap;
7878         t->glosstexture = r_texture_black;
7879         t->glowtexture = t->currentskinframe->glow;
7880         t->fogtexture = t->currentskinframe->fog;
7881         t->reflectmasktexture = t->currentskinframe->reflect;
7882         if (t->backgroundnumskinframes)
7883         {
7884                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7885                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7886                 t->backgroundglosstexture = r_texture_black;
7887                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7888                 if (!t->backgroundnmaptexture)
7889                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7890         }
7891         else
7892         {
7893                 t->backgroundbasetexture = r_texture_white;
7894                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7895                 t->backgroundglosstexture = r_texture_black;
7896                 t->backgroundglowtexture = NULL;
7897         }
7898         t->specularpower = r_shadow_glossexponent.value;
7899         // TODO: store reference values for these in the texture?
7900         t->specularscale = 0;
7901         if (r_shadow_gloss.integer > 0)
7902         {
7903                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7904                 {
7905                         if (r_shadow_glossintensity.value > 0)
7906                         {
7907                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7908                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7909                                 t->specularscale = r_shadow_glossintensity.value;
7910                         }
7911                 }
7912                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7913                 {
7914                         t->glosstexture = r_texture_white;
7915                         t->backgroundglosstexture = r_texture_white;
7916                         t->specularscale = r_shadow_gloss2intensity.value;
7917                         t->specularpower = r_shadow_gloss2exponent.value;
7918                 }
7919         }
7920         t->specularscale *= t->specularscalemod;
7921         t->specularpower *= t->specularpowermod;
7922         t->rtlightambient = 0;
7923
7924         // lightmaps mode looks bad with dlights using actual texturing, so turn
7925         // off the colormap and glossmap, but leave the normalmap on as it still
7926         // accurately represents the shading involved
7927         if (gl_lightmaps.integer)
7928         {
7929                 t->basetexture = r_texture_grey128;
7930                 t->pantstexture = r_texture_black;
7931                 t->shirttexture = r_texture_black;
7932                 t->nmaptexture = r_texture_blanknormalmap;
7933                 t->glosstexture = r_texture_black;
7934                 t->glowtexture = NULL;
7935                 t->fogtexture = NULL;
7936                 t->reflectmasktexture = NULL;
7937                 t->backgroundbasetexture = NULL;
7938                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7939                 t->backgroundglosstexture = r_texture_black;
7940                 t->backgroundglowtexture = NULL;
7941                 t->specularscale = 0;
7942                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7943         }
7944
7945         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7946         VectorClear(t->dlightcolor);
7947         t->currentnumlayers = 0;
7948         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7949         {
7950                 int blendfunc1, blendfunc2;
7951                 qboolean depthmask;
7952                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7953                 {
7954                         blendfunc1 = GL_SRC_ALPHA;
7955                         blendfunc2 = GL_ONE;
7956                 }
7957                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7958                 {
7959                         blendfunc1 = GL_SRC_ALPHA;
7960                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7961                 }
7962                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7963                 {
7964                         blendfunc1 = t->customblendfunc[0];
7965                         blendfunc2 = t->customblendfunc[1];
7966                 }
7967                 else
7968                 {
7969                         blendfunc1 = GL_ONE;
7970                         blendfunc2 = GL_ZERO;
7971                 }
7972                 // don't colormod evilblend textures
7973                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7974                         VectorSet(t->lightmapcolor, 1, 1, 1);
7975                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7976                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7977                 {
7978                         // fullbright is not affected by r_refdef.lightmapintensity
7979                         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]);
7980                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7981                                 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]);
7982                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7983                                 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]);
7984                 }
7985                 else
7986                 {
7987                         vec3_t ambientcolor;
7988                         float colorscale;
7989                         // set the color tint used for lights affecting this surface
7990                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7991                         colorscale = 2;
7992                         // q3bsp has no lightmap updates, so the lightstylevalue that
7993                         // would normally be baked into the lightmap must be
7994                         // applied to the color
7995                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7996                         if (model->type == mod_brushq3)
7997                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7998                         colorscale *= r_refdef.lightmapintensity;
7999                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8000                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8001                         // basic lit geometry
8002                         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]);
8003                         // add pants/shirt if needed
8004                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8005                                 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]);
8006                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8007                                 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]);
8008                         // now add ambient passes if needed
8009                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8010                         {
8011                                 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]);
8012                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8013                                         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]);
8014                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8015                                         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]);
8016                         }
8017                 }
8018                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8019                         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]);
8020                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8021                 {
8022                         // if this is opaque use alpha blend which will darken the earlier
8023                         // passes cheaply.
8024                         //
8025                         // if this is an alpha blended material, all the earlier passes
8026                         // were darkened by fog already, so we only need to add the fog
8027                         // color ontop through the fog mask texture
8028                         //
8029                         // if this is an additive blended material, all the earlier passes
8030                         // were darkened by fog already, and we should not add fog color
8031                         // (because the background was not darkened, there is no fog color
8032                         // that was lost behind it).
8033                         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]);
8034                 }
8035         }
8036
8037         return t->currentframe;
8038 }
8039
8040 rsurfacestate_t rsurface;
8041
8042 void RSurf_ActiveWorldEntity(void)
8043 {
8044         dp_model_t *model = r_refdef.scene.worldmodel;
8045         //if (rsurface.entity == r_refdef.scene.worldentity)
8046         //      return;
8047         rsurface.entity = r_refdef.scene.worldentity;
8048         rsurface.skeleton = NULL;
8049         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8050         rsurface.ent_skinnum = 0;
8051         rsurface.ent_qwskin = -1;
8052         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8053         rsurface.shadertime = r_refdef.scene.time;
8054         rsurface.matrix = identitymatrix;
8055         rsurface.inversematrix = identitymatrix;
8056         rsurface.matrixscale = 1;
8057         rsurface.inversematrixscale = 1;
8058         R_EntityMatrix(&identitymatrix);
8059         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8060         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8061         rsurface.fograngerecip = r_refdef.fograngerecip;
8062         rsurface.fogheightfade = r_refdef.fogheightfade;
8063         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8064         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8065         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8066         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8067         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8068         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8069         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8070         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8071         rsurface.colormod[3] = 1;
8072         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);
8073         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8074         rsurface.frameblend[0].lerp = 1;
8075         rsurface.ent_alttextures = false;
8076         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8077         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8078         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8079         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8081         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8082         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8084         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8085         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8086         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8087         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8088         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8089         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8090         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8091         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8092         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8093         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8094         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8095         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8096         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8097         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8098         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8099         rsurface.modelelement3i = model->surfmesh.data_element3i;
8100         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8101         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8102         rsurface.modelelement3s = model->surfmesh.data_element3s;
8103         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8104         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8105         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8106         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8107         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8108         rsurface.modelsurfaces = model->data_surfaces;
8109         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8110         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8111         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8112         rsurface.modelgeneratedvertex = false;
8113         rsurface.batchgeneratedvertex = false;
8114         rsurface.batchfirstvertex = 0;
8115         rsurface.batchnumvertices = 0;
8116         rsurface.batchfirsttriangle = 0;
8117         rsurface.batchnumtriangles = 0;
8118         rsurface.batchvertex3f  = NULL;
8119         rsurface.batchvertex3f_vertexbuffer = NULL;
8120         rsurface.batchvertex3f_bufferoffset = 0;
8121         rsurface.batchsvector3f = NULL;
8122         rsurface.batchsvector3f_vertexbuffer = NULL;
8123         rsurface.batchsvector3f_bufferoffset = 0;
8124         rsurface.batchtvector3f = NULL;
8125         rsurface.batchtvector3f_vertexbuffer = NULL;
8126         rsurface.batchtvector3f_bufferoffset = 0;
8127         rsurface.batchnormal3f  = NULL;
8128         rsurface.batchnormal3f_vertexbuffer = NULL;
8129         rsurface.batchnormal3f_bufferoffset = 0;
8130         rsurface.batchlightmapcolor4f = NULL;
8131         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8132         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8133         rsurface.batchtexcoordtexture2f = NULL;
8134         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8135         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8136         rsurface.batchtexcoordlightmap2f = NULL;
8137         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8138         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8139         rsurface.batchvertexmesh = NULL;
8140         rsurface.batchvertexmeshbuffer = NULL;
8141         rsurface.batchvertex3fbuffer = NULL;
8142         rsurface.batchelement3i = NULL;
8143         rsurface.batchelement3i_indexbuffer = NULL;
8144         rsurface.batchelement3i_bufferoffset = 0;
8145         rsurface.batchelement3s = NULL;
8146         rsurface.batchelement3s_indexbuffer = NULL;
8147         rsurface.batchelement3s_bufferoffset = 0;
8148         rsurface.passcolor4f = NULL;
8149         rsurface.passcolor4f_vertexbuffer = NULL;
8150         rsurface.passcolor4f_bufferoffset = 0;
8151 }
8152
8153 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8154 {
8155         dp_model_t *model = ent->model;
8156         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8157         //      return;
8158         rsurface.entity = (entity_render_t *)ent;
8159         rsurface.skeleton = ent->skeleton;
8160         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8161         rsurface.ent_skinnum = ent->skinnum;
8162         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;
8163         rsurface.ent_flags = ent->flags;
8164         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8165         rsurface.matrix = ent->matrix;
8166         rsurface.inversematrix = ent->inversematrix;
8167         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8168         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8169         R_EntityMatrix(&rsurface.matrix);
8170         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8171         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8172         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8173         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8174         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8175         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8176         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8177         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8178         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8179         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8180         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8181         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8182         rsurface.colormod[3] = ent->alpha;
8183         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8184         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8185         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8186         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8187         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8188         if (ent->model->brush.submodel && !prepass)
8189         {
8190                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8191                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8192         }
8193         if (model->surfmesh.isanimated && model->AnimateVertices)
8194         {
8195                 if (ent->animcache_vertex3f)
8196                 {
8197                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8198                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8199                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8200                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8201                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8202                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8203                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8204                 }
8205                 else if (wanttangents)
8206                 {
8207                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8208                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8209                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8210                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8211                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8212                         rsurface.modelvertexmesh = NULL;
8213                         rsurface.modelvertexmeshbuffer = NULL;
8214                         rsurface.modelvertex3fbuffer = NULL;
8215                 }
8216                 else if (wantnormals)
8217                 {
8218                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8219                         rsurface.modelsvector3f = NULL;
8220                         rsurface.modeltvector3f = NULL;
8221                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8222                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8223                         rsurface.modelvertexmesh = NULL;
8224                         rsurface.modelvertexmeshbuffer = NULL;
8225                         rsurface.modelvertex3fbuffer = NULL;
8226                 }
8227                 else
8228                 {
8229                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8230                         rsurface.modelsvector3f = NULL;
8231                         rsurface.modeltvector3f = NULL;
8232                         rsurface.modelnormal3f = NULL;
8233                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8234                         rsurface.modelvertexmesh = NULL;
8235                         rsurface.modelvertexmeshbuffer = NULL;
8236                         rsurface.modelvertex3fbuffer = NULL;
8237                 }
8238                 rsurface.modelvertex3f_vertexbuffer = 0;
8239                 rsurface.modelvertex3f_bufferoffset = 0;
8240                 rsurface.modelsvector3f_vertexbuffer = 0;
8241                 rsurface.modelsvector3f_bufferoffset = 0;
8242                 rsurface.modeltvector3f_vertexbuffer = 0;
8243                 rsurface.modeltvector3f_bufferoffset = 0;
8244                 rsurface.modelnormal3f_vertexbuffer = 0;
8245                 rsurface.modelnormal3f_bufferoffset = 0;
8246                 rsurface.modelgeneratedvertex = true;
8247         }
8248         else
8249         {
8250                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8251                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8253                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8254                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8256                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8257                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8259                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8260                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8261                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8262                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8263                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8264                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8265                 rsurface.modelgeneratedvertex = false;
8266         }
8267         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8268         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8270         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8271         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8273         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8274         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8275         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8276         rsurface.modelelement3i = model->surfmesh.data_element3i;
8277         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8278         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8279         rsurface.modelelement3s = model->surfmesh.data_element3s;
8280         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8281         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8282         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8283         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8284         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8285         rsurface.modelsurfaces = model->data_surfaces;
8286         rsurface.batchgeneratedvertex = false;
8287         rsurface.batchfirstvertex = 0;
8288         rsurface.batchnumvertices = 0;
8289         rsurface.batchfirsttriangle = 0;
8290         rsurface.batchnumtriangles = 0;
8291         rsurface.batchvertex3f  = NULL;
8292         rsurface.batchvertex3f_vertexbuffer = NULL;
8293         rsurface.batchvertex3f_bufferoffset = 0;
8294         rsurface.batchsvector3f = NULL;
8295         rsurface.batchsvector3f_vertexbuffer = NULL;
8296         rsurface.batchsvector3f_bufferoffset = 0;
8297         rsurface.batchtvector3f = NULL;
8298         rsurface.batchtvector3f_vertexbuffer = NULL;
8299         rsurface.batchtvector3f_bufferoffset = 0;
8300         rsurface.batchnormal3f  = NULL;
8301         rsurface.batchnormal3f_vertexbuffer = NULL;
8302         rsurface.batchnormal3f_bufferoffset = 0;
8303         rsurface.batchlightmapcolor4f = NULL;
8304         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8305         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8306         rsurface.batchtexcoordtexture2f = NULL;
8307         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8308         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8309         rsurface.batchtexcoordlightmap2f = NULL;
8310         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8311         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8312         rsurface.batchvertexmesh = NULL;
8313         rsurface.batchvertexmeshbuffer = NULL;
8314         rsurface.batchvertex3fbuffer = NULL;
8315         rsurface.batchelement3i = NULL;
8316         rsurface.batchelement3i_indexbuffer = NULL;
8317         rsurface.batchelement3i_bufferoffset = 0;
8318         rsurface.batchelement3s = NULL;
8319         rsurface.batchelement3s_indexbuffer = NULL;
8320         rsurface.batchelement3s_bufferoffset = 0;
8321         rsurface.passcolor4f = NULL;
8322         rsurface.passcolor4f_vertexbuffer = NULL;
8323         rsurface.passcolor4f_bufferoffset = 0;
8324 }
8325
8326 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)
8327 {
8328         rsurface.entity = r_refdef.scene.worldentity;
8329         rsurface.skeleton = NULL;
8330         rsurface.ent_skinnum = 0;
8331         rsurface.ent_qwskin = -1;
8332         rsurface.ent_flags = entflags;
8333         rsurface.shadertime = r_refdef.scene.time - shadertime;
8334         rsurface.modelnumvertices = numvertices;
8335         rsurface.modelnumtriangles = numtriangles;
8336         rsurface.matrix = *matrix;
8337         rsurface.inversematrix = *inversematrix;
8338         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8339         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8340         R_EntityMatrix(&rsurface.matrix);
8341         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8342         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8343         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8344         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8345         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8346         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8347         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8348         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8349         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8350         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8351         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8352         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8353         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);
8354         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8355         rsurface.frameblend[0].lerp = 1;
8356         rsurface.ent_alttextures = false;
8357         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8358         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8359         if (wanttangents)
8360         {
8361                 rsurface.modelvertex3f = (float *)vertex3f;
8362                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8363                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8364                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8365         }
8366         else if (wantnormals)
8367         {
8368                 rsurface.modelvertex3f = (float *)vertex3f;
8369                 rsurface.modelsvector3f = NULL;
8370                 rsurface.modeltvector3f = NULL;
8371                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8372         }
8373         else
8374         {
8375                 rsurface.modelvertex3f = (float *)vertex3f;
8376                 rsurface.modelsvector3f = NULL;
8377                 rsurface.modeltvector3f = NULL;
8378                 rsurface.modelnormal3f = NULL;
8379         }
8380         rsurface.modelvertexmesh = NULL;
8381         rsurface.modelvertexmeshbuffer = NULL;
8382         rsurface.modelvertex3fbuffer = NULL;
8383         rsurface.modelvertex3f_vertexbuffer = 0;
8384         rsurface.modelvertex3f_bufferoffset = 0;
8385         rsurface.modelsvector3f_vertexbuffer = 0;
8386         rsurface.modelsvector3f_bufferoffset = 0;
8387         rsurface.modeltvector3f_vertexbuffer = 0;
8388         rsurface.modeltvector3f_bufferoffset = 0;
8389         rsurface.modelnormal3f_vertexbuffer = 0;
8390         rsurface.modelnormal3f_bufferoffset = 0;
8391         rsurface.modelgeneratedvertex = true;
8392         rsurface.modellightmapcolor4f  = (float *)color4f;
8393         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8394         rsurface.modellightmapcolor4f_bufferoffset = 0;
8395         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8396         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8397         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8398         rsurface.modeltexcoordlightmap2f  = NULL;
8399         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8400         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8401         rsurface.modelelement3i = (int *)element3i;
8402         rsurface.modelelement3i_indexbuffer = NULL;
8403         rsurface.modelelement3i_bufferoffset = 0;
8404         rsurface.modelelement3s = (unsigned short *)element3s;
8405         rsurface.modelelement3s_indexbuffer = NULL;
8406         rsurface.modelelement3s_bufferoffset = 0;
8407         rsurface.modellightmapoffsets = NULL;
8408         rsurface.modelsurfaces = NULL;
8409         rsurface.batchgeneratedvertex = false;
8410         rsurface.batchfirstvertex = 0;
8411         rsurface.batchnumvertices = 0;
8412         rsurface.batchfirsttriangle = 0;
8413         rsurface.batchnumtriangles = 0;
8414         rsurface.batchvertex3f  = NULL;
8415         rsurface.batchvertex3f_vertexbuffer = NULL;
8416         rsurface.batchvertex3f_bufferoffset = 0;
8417         rsurface.batchsvector3f = NULL;
8418         rsurface.batchsvector3f_vertexbuffer = NULL;
8419         rsurface.batchsvector3f_bufferoffset = 0;
8420         rsurface.batchtvector3f = NULL;
8421         rsurface.batchtvector3f_vertexbuffer = NULL;
8422         rsurface.batchtvector3f_bufferoffset = 0;
8423         rsurface.batchnormal3f  = NULL;
8424         rsurface.batchnormal3f_vertexbuffer = NULL;
8425         rsurface.batchnormal3f_bufferoffset = 0;
8426         rsurface.batchlightmapcolor4f = NULL;
8427         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8428         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8429         rsurface.batchtexcoordtexture2f = NULL;
8430         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8431         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8432         rsurface.batchtexcoordlightmap2f = NULL;
8433         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8434         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8435         rsurface.batchvertexmesh = NULL;
8436         rsurface.batchvertexmeshbuffer = NULL;
8437         rsurface.batchvertex3fbuffer = NULL;
8438         rsurface.batchelement3i = NULL;
8439         rsurface.batchelement3i_indexbuffer = NULL;
8440         rsurface.batchelement3i_bufferoffset = 0;
8441         rsurface.batchelement3s = NULL;
8442         rsurface.batchelement3s_indexbuffer = NULL;
8443         rsurface.batchelement3s_bufferoffset = 0;
8444         rsurface.passcolor4f = NULL;
8445         rsurface.passcolor4f_vertexbuffer = NULL;
8446         rsurface.passcolor4f_bufferoffset = 0;
8447
8448         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8449         {
8450                 if ((wantnormals || wanttangents) && !normal3f)
8451                 {
8452                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8453                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8454                 }
8455                 if (wanttangents && !svector3f)
8456                 {
8457                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8458                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8459                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8460                 }
8461         }
8462 }
8463
8464 float RSurf_FogPoint(const float *v)
8465 {
8466         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8467         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8468         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8469         float FogHeightFade = r_refdef.fogheightfade;
8470         float fogfrac;
8471         unsigned int fogmasktableindex;
8472         if (r_refdef.fogplaneviewabove)
8473                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8474         else
8475                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8476         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8477         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8478 }
8479
8480 float RSurf_FogVertex(const float *v)
8481 {
8482         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8483         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8484         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8485         float FogHeightFade = rsurface.fogheightfade;
8486         float fogfrac;
8487         unsigned int fogmasktableindex;
8488         if (r_refdef.fogplaneviewabove)
8489                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8490         else
8491                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8492         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8493         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8494 }
8495
8496 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8497 {
8498         int i;
8499         for (i = 0;i < numelements;i++)
8500                 outelement3i[i] = inelement3i[i] + adjust;
8501 }
8502
8503 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8504 extern cvar_t gl_vbo;
8505 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8506 {
8507         int deformindex;
8508         int firsttriangle;
8509         int numtriangles;
8510         int firstvertex;
8511         int endvertex;
8512         int numvertices;
8513         int surfacefirsttriangle;
8514         int surfacenumtriangles;
8515         int surfacefirstvertex;
8516         int surfaceendvertex;
8517         int surfacenumvertices;
8518         int batchnumvertices;
8519         int batchnumtriangles;
8520         int needsupdate;
8521         int i, j;
8522         qboolean gaps;
8523         qboolean dynamicvertex;
8524         float amplitude;
8525         float animpos;
8526         float scale;
8527         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8528         float waveparms[4];
8529         q3shaderinfo_deform_t *deform;
8530         const msurface_t *surface, *firstsurface;
8531         r_vertexmesh_t *vertexmesh;
8532         if (!texturenumsurfaces)
8533                 return;
8534         // find vertex range of this surface batch
8535         gaps = false;
8536         firstsurface = texturesurfacelist[0];
8537         firsttriangle = firstsurface->num_firsttriangle;
8538         batchnumvertices = 0;
8539         batchnumtriangles = 0;
8540         firstvertex = endvertex = firstsurface->num_firstvertex;
8541         for (i = 0;i < texturenumsurfaces;i++)
8542         {
8543                 surface = texturesurfacelist[i];
8544                 if (surface != firstsurface + i)
8545                         gaps = true;
8546                 surfacefirstvertex = surface->num_firstvertex;
8547                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8548                 surfacenumvertices = surface->num_vertices;
8549                 surfacenumtriangles = surface->num_triangles;
8550                 if (firstvertex > surfacefirstvertex)
8551                         firstvertex = surfacefirstvertex;
8552                 if (endvertex < surfaceendvertex)
8553                         endvertex = surfaceendvertex;
8554                 batchnumvertices += surfacenumvertices;
8555                 batchnumtriangles += surfacenumtriangles;
8556         }
8557
8558         // we now know the vertex range used, and if there are any gaps in it
8559         rsurface.batchfirstvertex = firstvertex;
8560         rsurface.batchnumvertices = endvertex - firstvertex;
8561         rsurface.batchfirsttriangle = firsttriangle;
8562         rsurface.batchnumtriangles = batchnumtriangles;
8563
8564         // this variable holds flags for which properties have been updated that
8565         // may require regenerating vertexmesh array...
8566         needsupdate = 0;
8567
8568         // check if any dynamic vertex processing must occur
8569         dynamicvertex = false;
8570
8571         // if there is a chance of animated vertex colors, it's a dynamic batch
8572         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8573         {
8574                 dynamicvertex = true;
8575                 batchneed |= BATCHNEED_NOGAPS;
8576                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8577         }
8578
8579         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8580         {
8581                 switch (deform->deform)
8582                 {
8583                 default:
8584                 case Q3DEFORM_PROJECTIONSHADOW:
8585                 case Q3DEFORM_TEXT0:
8586                 case Q3DEFORM_TEXT1:
8587                 case Q3DEFORM_TEXT2:
8588                 case Q3DEFORM_TEXT3:
8589                 case Q3DEFORM_TEXT4:
8590                 case Q3DEFORM_TEXT5:
8591                 case Q3DEFORM_TEXT6:
8592                 case Q3DEFORM_TEXT7:
8593                 case Q3DEFORM_NONE:
8594                         break;
8595                 case Q3DEFORM_AUTOSPRITE:
8596                         dynamicvertex = true;
8597                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8598                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8599                         break;
8600                 case Q3DEFORM_AUTOSPRITE2:
8601                         dynamicvertex = true;
8602                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8603                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8604                         break;
8605                 case Q3DEFORM_NORMAL:
8606                         dynamicvertex = true;
8607                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8608                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8609                         break;
8610                 case Q3DEFORM_WAVE:
8611                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8612                                 break; // if wavefunc is a nop, ignore this transform
8613                         dynamicvertex = true;
8614                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8615                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8616                         break;
8617                 case Q3DEFORM_BULGE:
8618                         dynamicvertex = true;
8619                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8620                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8621                         break;
8622                 case Q3DEFORM_MOVE:
8623                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8624                                 break; // if wavefunc is a nop, ignore this transform
8625                         dynamicvertex = true;
8626                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8627                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8628                         break;
8629                 }
8630         }
8631         switch(rsurface.texture->tcgen.tcgen)
8632         {
8633         default:
8634         case Q3TCGEN_TEXTURE:
8635                 break;
8636         case Q3TCGEN_LIGHTMAP:
8637                 dynamicvertex = true;
8638                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8639                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8640                 break;
8641         case Q3TCGEN_VECTOR:
8642                 dynamicvertex = true;
8643                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8644                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8645                 break;
8646         case Q3TCGEN_ENVIRONMENT:
8647                 dynamicvertex = true;
8648                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8649                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8650                 break;
8651         }
8652         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8653         {
8654                 dynamicvertex = true;
8655                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8657         }
8658
8659         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8660         {
8661                 dynamicvertex = true;
8662                 batchneed |= BATCHNEED_NOGAPS;
8663                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8664         }
8665
8666         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8667         {
8668                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8669                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8670                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8671                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8672                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8673                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8674                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8675         }
8676
8677         // when the model data has no vertex buffer (dynamic mesh), we need to
8678         // eliminate gaps
8679         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8680                 batchneed |= BATCHNEED_NOGAPS;
8681
8682         // if needsupdate, we have to do a dynamic vertex batch for sure
8683         if (needsupdate & batchneed)
8684                 dynamicvertex = true;
8685
8686         // see if we need to build vertexmesh from arrays
8687         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8688                 dynamicvertex = true;
8689
8690         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8691         // also some drivers strongly dislike firstvertex
8692         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8693                 dynamicvertex = true;
8694
8695         rsurface.batchvertex3f = rsurface.modelvertex3f;
8696         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8697         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8698         rsurface.batchsvector3f = rsurface.modelsvector3f;
8699         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8700         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8701         rsurface.batchtvector3f = rsurface.modeltvector3f;
8702         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8703         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8704         rsurface.batchnormal3f = rsurface.modelnormal3f;
8705         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8706         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8707         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8708         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8709         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8710         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8711         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8712         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8713         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8714         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8715         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8716         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8717         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8718         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8719         rsurface.batchelement3i = rsurface.modelelement3i;
8720         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8721         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8722         rsurface.batchelement3s = rsurface.modelelement3s;
8723         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8724         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8725
8726         // if any dynamic vertex processing has to occur in software, we copy the
8727         // entire surface list together before processing to rebase the vertices
8728         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8729         //
8730         // if any gaps exist and we do not have a static vertex buffer, we have to
8731         // copy the surface list together to avoid wasting upload bandwidth on the
8732         // vertices in the gaps.
8733         //
8734         // if gaps exist and we have a static vertex buffer, we still have to
8735         // combine the index buffer ranges into one dynamic index buffer.
8736         //
8737         // in all cases we end up with data that can be drawn in one call.
8738
8739         if (!dynamicvertex)
8740         {
8741                 // static vertex data, just set pointers...
8742                 rsurface.batchgeneratedvertex = false;
8743                 // if there are gaps, we want to build a combined index buffer,
8744                 // otherwise use the original static buffer with an appropriate offset
8745                 if (gaps)
8746                 {
8747                         // build a new triangle elements array for this batch
8748                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8749                         rsurface.batchfirsttriangle = 0;
8750                         numtriangles = 0;
8751                         for (i = 0;i < texturenumsurfaces;i++)
8752                         {
8753                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8754                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8755                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8756                                 numtriangles += surfacenumtriangles;
8757                         }
8758                         rsurface.batchelement3i_indexbuffer = NULL;
8759                         rsurface.batchelement3i_bufferoffset = 0;
8760                         rsurface.batchelement3s = NULL;
8761                         rsurface.batchelement3s_indexbuffer = NULL;
8762                         rsurface.batchelement3s_bufferoffset = 0;
8763                         if (endvertex <= 65536)
8764                         {
8765                                 // make a 16bit (unsigned short) index array if possible
8766                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8767                                 for (i = 0;i < numtriangles*3;i++)
8768                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8769                         }
8770                 }
8771                 return;
8772         }
8773
8774         // something needs software processing, do it for real...
8775         // we only directly handle separate array data in this case and then
8776         // generate interleaved data if needed...
8777         rsurface.batchgeneratedvertex = true;
8778
8779         // now copy the vertex data into a combined array and make an index array
8780         // (this is what Quake3 does all the time)
8781         //if (gaps || rsurface.batchfirstvertex)
8782         {
8783                 rsurface.batchvertex3fbuffer = NULL;
8784                 rsurface.batchvertexmesh = NULL;
8785                 rsurface.batchvertexmeshbuffer = NULL;
8786                 rsurface.batchvertex3f = NULL;
8787                 rsurface.batchvertex3f_vertexbuffer = NULL;
8788                 rsurface.batchvertex3f_bufferoffset = 0;
8789                 rsurface.batchsvector3f = NULL;
8790                 rsurface.batchsvector3f_vertexbuffer = NULL;
8791                 rsurface.batchsvector3f_bufferoffset = 0;
8792                 rsurface.batchtvector3f = NULL;
8793                 rsurface.batchtvector3f_vertexbuffer = NULL;
8794                 rsurface.batchtvector3f_bufferoffset = 0;
8795                 rsurface.batchnormal3f = NULL;
8796                 rsurface.batchnormal3f_vertexbuffer = NULL;
8797                 rsurface.batchnormal3f_bufferoffset = 0;
8798                 rsurface.batchlightmapcolor4f = NULL;
8799                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8800                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8801                 rsurface.batchtexcoordtexture2f = NULL;
8802                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8803                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8804                 rsurface.batchtexcoordlightmap2f = NULL;
8805                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8806                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8807                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
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                 // we'll only be setting up certain arrays as needed
8814                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8815                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8816                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8817                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8819                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8821                 {
8822                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8823                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8824                 }
8825                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8826                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8827                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8828                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8829                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8830                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8831                 numvertices = 0;
8832                 numtriangles = 0;
8833                 for (i = 0;i < texturenumsurfaces;i++)
8834                 {
8835                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8836                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8837                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8838                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8839                         // copy only the data requested
8840                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8841                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8842                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8843                         {
8844                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8845                                 {
8846                                         if (rsurface.batchvertex3f)
8847                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8848                                         else
8849                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8850                                 }
8851                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8852                                 {
8853                                         if (rsurface.modelnormal3f)
8854                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8855                                         else
8856                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8857                                 }
8858                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8859                                 {
8860                                         if (rsurface.modelsvector3f)
8861                                         {
8862                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8863                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8864                                         }
8865                                         else
8866                                         {
8867                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8868                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8869                                         }
8870                                 }
8871                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8872                                 {
8873                                         if (rsurface.modellightmapcolor4f)
8874                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8875                                         else
8876                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8877                                 }
8878                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8879                                 {
8880                                         if (rsurface.modeltexcoordtexture2f)
8881                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8882                                         else
8883                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8884                                 }
8885                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8886                                 {
8887                                         if (rsurface.modeltexcoordlightmap2f)
8888                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8889                                         else
8890                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8891                                 }
8892                         }
8893                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8894                         numvertices += surfacenumvertices;
8895                         numtriangles += surfacenumtriangles;
8896                 }
8897
8898                 // generate a 16bit index array as well if possible
8899                 // (in general, dynamic batches fit)
8900                 if (numvertices <= 65536)
8901                 {
8902                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8903                         for (i = 0;i < numtriangles*3;i++)
8904                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8905                 }
8906
8907                 // since we've copied everything, the batch now starts at 0
8908                 rsurface.batchfirstvertex = 0;
8909                 rsurface.batchnumvertices = batchnumvertices;
8910                 rsurface.batchfirsttriangle = 0;
8911                 rsurface.batchnumtriangles = batchnumtriangles;
8912         }
8913
8914         // q1bsp surfaces rendered in vertex color mode have to have colors
8915         // calculated based on lightstyles
8916         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8917         {
8918                 // generate color arrays for the surfaces in this list
8919                 int c[4];
8920                 int scale;
8921                 int size3;
8922                 const int *offsets;
8923                 const unsigned char *lm;
8924                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8925                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8926                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8927                 numvertices = 0;
8928                 for (i = 0;i < texturenumsurfaces;i++)
8929                 {
8930                         surface = texturesurfacelist[i];
8931                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8932                         surfacenumvertices = surface->num_vertices;
8933                         if (surface->lightmapinfo->samples)
8934                         {
8935                                 for (j = 0;j < surfacenumvertices;j++)
8936                                 {
8937                                         lm = surface->lightmapinfo->samples + offsets[j];
8938                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8939                                         VectorScale(lm, scale, c);
8940                                         if (surface->lightmapinfo->styles[1] != 255)
8941                                         {
8942                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8943                                                 lm += size3;
8944                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8945                                                 VectorMA(c, scale, lm, c);
8946                                                 if (surface->lightmapinfo->styles[2] != 255)
8947                                                 {
8948                                                         lm += size3;
8949                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8950                                                         VectorMA(c, scale, lm, c);
8951                                                         if (surface->lightmapinfo->styles[3] != 255)
8952                                                         {
8953                                                                 lm += size3;
8954                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8955                                                                 VectorMA(c, scale, lm, c);
8956                                                         }
8957                                                 }
8958                                         }
8959                                         c[0] >>= 7;
8960                                         c[1] >>= 7;
8961                                         c[2] >>= 7;
8962                                         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);
8963                                         numvertices++;
8964                                 }
8965                         }
8966                         else
8967                         {
8968                                 for (j = 0;j < surfacenumvertices;j++)
8969                                 {
8970                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8971                                         numvertices++;
8972                                 }
8973                         }
8974                 }
8975         }
8976
8977         // if vertices are deformed (sprite flares and things in maps, possibly
8978         // water waves, bulges and other deformations), modify the copied vertices
8979         // in place
8980         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8981         {
8982                 switch (deform->deform)
8983                 {
8984                 default:
8985                 case Q3DEFORM_PROJECTIONSHADOW:
8986                 case Q3DEFORM_TEXT0:
8987                 case Q3DEFORM_TEXT1:
8988                 case Q3DEFORM_TEXT2:
8989                 case Q3DEFORM_TEXT3:
8990                 case Q3DEFORM_TEXT4:
8991                 case Q3DEFORM_TEXT5:
8992                 case Q3DEFORM_TEXT6:
8993                 case Q3DEFORM_TEXT7:
8994                 case Q3DEFORM_NONE:
8995                         break;
8996                 case Q3DEFORM_AUTOSPRITE:
8997                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8998                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8999                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9000                         VectorNormalize(newforward);
9001                         VectorNormalize(newright);
9002                         VectorNormalize(newup);
9003 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9004 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9005 //                      rsurface.batchvertex3f_bufferoffset = 0;
9006 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9007 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9008 //                      rsurface.batchsvector3f_bufferoffset = 0;
9009 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9010 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9011 //                      rsurface.batchtvector3f_bufferoffset = 0;
9012 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9013 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9014 //                      rsurface.batchnormal3f_bufferoffset = 0;
9015                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9016                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9017                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9018                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9019                                 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);
9020                         // a single autosprite surface can contain multiple sprites...
9021                         for (j = 0;j < batchnumvertices - 3;j += 4)
9022                         {
9023                                 VectorClear(center);
9024                                 for (i = 0;i < 4;i++)
9025                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9026                                 VectorScale(center, 0.25f, center);
9027                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9028                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9029                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9030                                 for (i = 0;i < 4;i++)
9031                                 {
9032                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9033                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9034                                 }
9035                         }
9036                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9037                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9038                         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);
9039                         break;
9040                 case Q3DEFORM_AUTOSPRITE2:
9041                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9042                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9043                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9044                         VectorNormalize(newforward);
9045                         VectorNormalize(newright);
9046                         VectorNormalize(newup);
9047 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9048 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9049 //                      rsurface.batchvertex3f_bufferoffset = 0;
9050                         {
9051                                 const float *v1, *v2;
9052                                 vec3_t start, end;
9053                                 float f, l;
9054                                 struct
9055                                 {
9056                                         float length2;
9057                                         const float *v1;
9058                                         const float *v2;
9059                                 }
9060                                 shortest[2];
9061                                 memset(shortest, 0, sizeof(shortest));
9062                                 // a single autosprite surface can contain multiple sprites...
9063                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9064                                 {
9065                                         VectorClear(center);
9066                                         for (i = 0;i < 4;i++)
9067                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9068                                         VectorScale(center, 0.25f, center);
9069                                         // find the two shortest edges, then use them to define the
9070                                         // axis vectors for rotating around the central axis
9071                                         for (i = 0;i < 6;i++)
9072                                         {
9073                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9074                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9075                                                 l = VectorDistance2(v1, v2);
9076                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9077                                                 if (v1[2] != v2[2])
9078                                                         l += (1.0f / 1024.0f);
9079                                                 if (shortest[0].length2 > l || i == 0)
9080                                                 {
9081                                                         shortest[1] = shortest[0];
9082                                                         shortest[0].length2 = l;
9083                                                         shortest[0].v1 = v1;
9084                                                         shortest[0].v2 = v2;
9085                                                 }
9086                                                 else if (shortest[1].length2 > l || i == 1)
9087                                                 {
9088                                                         shortest[1].length2 = l;
9089                                                         shortest[1].v1 = v1;
9090                                                         shortest[1].v2 = v2;
9091                                                 }
9092                                         }
9093                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9094                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9095                                         // this calculates the right vector from the shortest edge
9096                                         // and the up vector from the edge midpoints
9097                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9098                                         VectorNormalize(right);
9099                                         VectorSubtract(end, start, up);
9100                                         VectorNormalize(up);
9101                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9102                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9103                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9104                                         VectorNegate(forward, forward);
9105                                         VectorReflect(forward, 0, up, forward);
9106                                         VectorNormalize(forward);
9107                                         CrossProduct(up, forward, newright);
9108                                         VectorNormalize(newright);
9109                                         // rotate the quad around the up axis vector, this is made
9110                                         // especially easy by the fact we know the quad is flat,
9111                                         // so we only have to subtract the center position and
9112                                         // measure distance along the right vector, and then
9113                                         // multiply that by the newright vector and add back the
9114                                         // center position
9115                                         // we also need to subtract the old position to undo the
9116                                         // displacement from the center, which we do with a
9117                                         // DotProduct, the subtraction/addition of center is also
9118                                         // optimized into DotProducts here
9119                                         l = DotProduct(right, center);
9120                                         for (i = 0;i < 4;i++)
9121                                         {
9122                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9123                                                 f = DotProduct(right, v1) - l;
9124                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9125                                         }
9126                                 }
9127                         }
9128                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9129                         {
9130 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9131 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9132 //                              rsurface.batchnormal3f_bufferoffset = 0;
9133                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9134                         }
9135                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9136                         {
9137 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9139 //                              rsurface.batchsvector3f_bufferoffset = 0;
9140 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9141 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9142 //                              rsurface.batchtvector3f_bufferoffset = 0;
9143                                 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);
9144                         }
9145                         break;
9146                 case Q3DEFORM_NORMAL:
9147                         // deform the normals to make reflections wavey
9148                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9149                         rsurface.batchnormal3f_vertexbuffer = NULL;
9150                         rsurface.batchnormal3f_bufferoffset = 0;
9151                         for (j = 0;j < batchnumvertices;j++)
9152                         {
9153                                 float vertex[3];
9154                                 float *normal = rsurface.batchnormal3f + 3*j;
9155                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9156                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9157                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9158                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9159                                 VectorNormalize(normal);
9160                         }
9161                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9162                         {
9163 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9165 //                              rsurface.batchsvector3f_bufferoffset = 0;
9166 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9167 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9168 //                              rsurface.batchtvector3f_bufferoffset = 0;
9169                                 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);
9170                         }
9171                         break;
9172                 case Q3DEFORM_WAVE:
9173                         // deform vertex array to make wavey water and flags and such
9174                         waveparms[0] = deform->waveparms[0];
9175                         waveparms[1] = deform->waveparms[1];
9176                         waveparms[2] = deform->waveparms[2];
9177                         waveparms[3] = deform->waveparms[3];
9178                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9179                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9180                         // this is how a divisor of vertex influence on deformation
9181                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9182                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9183 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9184 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9185 //                      rsurface.batchvertex3f_bufferoffset = 0;
9186 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9187 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9188 //                      rsurface.batchnormal3f_bufferoffset = 0;
9189                         for (j = 0;j < batchnumvertices;j++)
9190                         {
9191                                 // if the wavefunc depends on time, evaluate it per-vertex
9192                                 if (waveparms[3])
9193                                 {
9194                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9195                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9196                                 }
9197                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9198                         }
9199                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9200                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9201                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9202                         {
9203 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9205 //                              rsurface.batchsvector3f_bufferoffset = 0;
9206 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9207 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9208 //                              rsurface.batchtvector3f_bufferoffset = 0;
9209                                 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);
9210                         }
9211                         break;
9212                 case Q3DEFORM_BULGE:
9213                         // deform vertex array to make the surface have moving bulges
9214 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9215 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9216 //                      rsurface.batchvertex3f_bufferoffset = 0;
9217 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9218 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9219 //                      rsurface.batchnormal3f_bufferoffset = 0;
9220                         for (j = 0;j < batchnumvertices;j++)
9221                         {
9222                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9223                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9224                         }
9225                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9226                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9227                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9228                         {
9229 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9230 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9231 //                              rsurface.batchsvector3f_bufferoffset = 0;
9232 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9233 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9234 //                              rsurface.batchtvector3f_bufferoffset = 0;
9235                                 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);
9236                         }
9237                         break;
9238                 case Q3DEFORM_MOVE:
9239                         // deform vertex array
9240                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9241                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9242                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9243                         VectorScale(deform->parms, scale, waveparms);
9244 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9245 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9246 //                      rsurface.batchvertex3f_bufferoffset = 0;
9247                         for (j = 0;j < batchnumvertices;j++)
9248                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9249                         break;
9250                 }
9251         }
9252
9253         // generate texcoords based on the chosen texcoord source
9254         switch(rsurface.texture->tcgen.tcgen)
9255         {
9256         default:
9257         case Q3TCGEN_TEXTURE:
9258                 break;
9259         case Q3TCGEN_LIGHTMAP:
9260 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9261 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9262 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9263                 if (rsurface.batchtexcoordlightmap2f)
9264                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9265                 break;
9266         case Q3TCGEN_VECTOR:
9267 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9268 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9269 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9270                 for (j = 0;j < batchnumvertices;j++)
9271                 {
9272                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9273                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9274                 }
9275                 break;
9276         case Q3TCGEN_ENVIRONMENT:
9277                 // make environment reflections using a spheremap
9278                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9279                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9280                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9281                 for (j = 0;j < batchnumvertices;j++)
9282                 {
9283                         // identical to Q3A's method, but executed in worldspace so
9284                         // carried models can be shiny too
9285
9286                         float viewer[3], d, reflected[3], worldreflected[3];
9287
9288                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9289                         // VectorNormalize(viewer);
9290
9291                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9292
9293                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9294                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9295                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9296                         // note: this is proportinal to viewer, so we can normalize later
9297
9298                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9299                         VectorNormalize(worldreflected);
9300
9301                         // note: this sphere map only uses world x and z!
9302                         // so positive and negative y will LOOK THE SAME.
9303                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9304                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9305                 }
9306                 break;
9307         }
9308         // the only tcmod that needs software vertex processing is turbulent, so
9309         // check for it here and apply the changes if needed
9310         // and we only support that as the first one
9311         // (handling a mixture of turbulent and other tcmods would be problematic
9312         //  without punting it entirely to a software path)
9313         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9314         {
9315                 amplitude = rsurface.texture->tcmods[0].parms[1];
9316                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
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] += amplitude * sin(((rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+2]) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9323                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9324                 }
9325         }
9326
9327         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9328         {
9329                 // convert the modified arrays to vertex structs
9330 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9331 //              rsurface.batchvertexmeshbuffer = NULL;
9332                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9333                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9335                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9336                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9337                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9338                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9339                 {
9340                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9341                         {
9342                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9343                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9344                         }
9345                 }
9346                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9347                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9348                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9349                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9350                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9351                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9352                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9353                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9354                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9355         }
9356 }
9357
9358 void RSurf_DrawBatch(void)
9359 {
9360         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9361         // through the pipeline, killing it earlier in the pipeline would have
9362         // per-surface overhead rather than per-batch overhead, so it's best to
9363         // reject it here, before it hits glDraw.
9364         if (rsurface.batchnumtriangles == 0)
9365                 return;
9366 #if 0
9367         // batch debugging code
9368         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9369         {
9370                 int i;
9371                 int j;
9372                 int c;
9373                 const int *e;
9374                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9375                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9376                 {
9377                         c = e[i];
9378                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9379                         {
9380                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9381                                 {
9382                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9383                                                 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);
9384                                         break;
9385                                 }
9386                         }
9387                 }
9388         }
9389 #endif
9390         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);
9391 }
9392
9393 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9394 {
9395         // pick the closest matching water plane
9396         int planeindex, vertexindex, bestplaneindex = -1;
9397         float d, bestd;
9398         vec3_t vert;
9399         const float *v;
9400         r_waterstate_waterplane_t *p;
9401         qboolean prepared = false;
9402         bestd = 0;
9403         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9404         {
9405                 if(p->camera_entity != rsurface.texture->camera_entity)
9406                         continue;
9407                 d = 0;
9408                 if(!prepared)
9409                 {
9410                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9411                         prepared = true;
9412                         if(rsurface.batchnumvertices == 0)
9413                                 break;
9414                 }
9415                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9416                 {
9417                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9418                         d += fabs(PlaneDiff(vert, &p->plane));
9419                 }
9420                 if (bestd > d || bestplaneindex < 0)
9421                 {
9422                         bestd = d;
9423                         bestplaneindex = planeindex;
9424                 }
9425         }
9426         return bestplaneindex;
9427         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9428         // this situation though, as it might be better to render single larger
9429         // batches with useless stuff (backface culled for example) than to
9430         // render multiple smaller batches
9431 }
9432
9433 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9434 {
9435         int i;
9436         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9437         rsurface.passcolor4f_vertexbuffer = 0;
9438         rsurface.passcolor4f_bufferoffset = 0;
9439         for (i = 0;i < rsurface.batchnumvertices;i++)
9440                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9441 }
9442
9443 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9444 {
9445         int i;
9446         float f;
9447         const float *v;
9448         const float *c;
9449         float *c2;
9450         if (rsurface.passcolor4f)
9451         {
9452                 // generate color arrays
9453                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9454                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9455                 rsurface.passcolor4f_vertexbuffer = 0;
9456                 rsurface.passcolor4f_bufferoffset = 0;
9457                 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)
9458                 {
9459                         f = RSurf_FogVertex(v);
9460                         c2[0] = c[0] * f;
9461                         c2[1] = c[1] * f;
9462                         c2[2] = c[2] * f;
9463                         c2[3] = c[3];
9464                 }
9465         }
9466         else
9467         {
9468                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9469                 rsurface.passcolor4f_vertexbuffer = 0;
9470                 rsurface.passcolor4f_bufferoffset = 0;
9471                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9472                 {
9473                         f = RSurf_FogVertex(v);
9474                         c2[0] = f;
9475                         c2[1] = f;
9476                         c2[2] = f;
9477                         c2[3] = 1;
9478                 }
9479         }
9480 }
9481
9482 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9483 {
9484         int i;
9485         float f;
9486         const float *v;
9487         const float *c;
9488         float *c2;
9489         if (!rsurface.passcolor4f)
9490                 return;
9491         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9492         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9493         rsurface.passcolor4f_vertexbuffer = 0;
9494         rsurface.passcolor4f_bufferoffset = 0;
9495         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)
9496         {
9497                 f = RSurf_FogVertex(v);
9498                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9499                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9500                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9501                 c2[3] = c[3];
9502         }
9503 }
9504
9505 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9506 {
9507         int i;
9508         const float *c;
9509         float *c2;
9510         if (!rsurface.passcolor4f)
9511                 return;
9512         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9513         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9514         rsurface.passcolor4f_vertexbuffer = 0;
9515         rsurface.passcolor4f_bufferoffset = 0;
9516         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9517         {
9518                 c2[0] = c[0] * r;
9519                 c2[1] = c[1] * g;
9520                 c2[2] = c[2] * b;
9521                 c2[3] = c[3] * a;
9522         }
9523 }
9524
9525 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9526 {
9527         int i;
9528         const float *c;
9529         float *c2;
9530         if (!rsurface.passcolor4f)
9531                 return;
9532         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9533         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9534         rsurface.passcolor4f_vertexbuffer = 0;
9535         rsurface.passcolor4f_bufferoffset = 0;
9536         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9537         {
9538                 c2[0] = c[0] + r_refdef.scene.ambient;
9539                 c2[1] = c[1] + r_refdef.scene.ambient;
9540                 c2[2] = c[2] + r_refdef.scene.ambient;
9541                 c2[3] = c[3];
9542         }
9543 }
9544
9545 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9546 {
9547         // TODO: optimize
9548         rsurface.passcolor4f = NULL;
9549         rsurface.passcolor4f_vertexbuffer = 0;
9550         rsurface.passcolor4f_bufferoffset = 0;
9551         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9552         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9553         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9554         GL_Color(r, g, b, a);
9555         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9556         RSurf_DrawBatch();
9557 }
9558
9559 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9560 {
9561         // TODO: optimize applyfog && applycolor case
9562         // just apply fog if necessary, and tint the fog color array if necessary
9563         rsurface.passcolor4f = NULL;
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9567         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9568         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9569         GL_Color(r, g, b, a);
9570         RSurf_DrawBatch();
9571 }
9572
9573 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9574 {
9575         // TODO: optimize
9576         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9577         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9578         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9579         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9580         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9581         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9582         GL_Color(r, g, b, a);
9583         RSurf_DrawBatch();
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_ClampColor(void)
9587 {
9588         int i;
9589         const float *c1;
9590         float *c2;
9591         if (!rsurface.passcolor4f)
9592                 return;
9593         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9594         {
9595                 c2[0] = bound(0.0f, c1[0], 1.0f);
9596                 c2[1] = bound(0.0f, c1[1], 1.0f);
9597                 c2[2] = bound(0.0f, c1[2], 1.0f);
9598                 c2[3] = bound(0.0f, c1[3], 1.0f);
9599         }
9600 }
9601
9602 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9603 {
9604         int i;
9605         float f;
9606         const float *v;
9607         const float *n;
9608         float *c;
9609         //vec3_t eyedir;
9610
9611         // fake shading
9612         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9613         rsurface.passcolor4f_vertexbuffer = 0;
9614         rsurface.passcolor4f_bufferoffset = 0;
9615         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)
9616         {
9617                 f = -DotProduct(r_refdef.view.forward, n);
9618                 f = max(0, f);
9619                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9620                 f *= r_refdef.lightmapintensity;
9621                 Vector4Set(c, f, f, f, 1);
9622         }
9623 }
9624
9625 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9626 {
9627         RSurf_DrawBatch_GL11_ApplyFakeLight();
9628         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9629         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9630         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9631         GL_Color(r, g, b, a);
9632         RSurf_DrawBatch();
9633 }
9634
9635 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9636 {
9637         int i;
9638         float f;
9639         float alpha;
9640         const float *v;
9641         const float *n;
9642         float *c;
9643         vec3_t ambientcolor;
9644         vec3_t diffusecolor;
9645         vec3_t lightdir;
9646         // TODO: optimize
9647         // model lighting
9648         VectorCopy(rsurface.modellight_lightdir, lightdir);
9649         f = 0.5f * r_refdef.lightmapintensity;
9650         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9651         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9652         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9653         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9654         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9655         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9656         alpha = *a;
9657         if (VectorLength2(diffusecolor) > 0)
9658         {
9659                 // q3-style directional shading
9660                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9661                 rsurface.passcolor4f_vertexbuffer = 0;
9662                 rsurface.passcolor4f_bufferoffset = 0;
9663                 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)
9664                 {
9665                         if ((f = DotProduct(n, lightdir)) > 0)
9666                                 VectorMA(ambientcolor, f, diffusecolor, c);
9667                         else
9668                                 VectorCopy(ambientcolor, c);
9669                         c[3] = alpha;
9670                 }
9671                 *r = 1;
9672                 *g = 1;
9673                 *b = 1;
9674                 *a = 1;
9675                 *applycolor = false;
9676         }
9677         else
9678         {
9679                 *r = ambientcolor[0];
9680                 *g = ambientcolor[1];
9681                 *b = ambientcolor[2];
9682                 rsurface.passcolor4f = NULL;
9683                 rsurface.passcolor4f_vertexbuffer = 0;
9684                 rsurface.passcolor4f_bufferoffset = 0;
9685         }
9686 }
9687
9688 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9689 {
9690         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9691         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9692         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9693         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9694         GL_Color(r, g, b, a);
9695         RSurf_DrawBatch();
9696 }
9697
9698 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9699 {
9700         int i;
9701         float f;
9702         const float *v;
9703         float *c;
9704
9705         // fake shading
9706         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9707         rsurface.passcolor4f_vertexbuffer = 0;
9708         rsurface.passcolor4f_bufferoffset = 0;
9709
9710         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9711         {
9712                 f = 1 - RSurf_FogVertex(v);
9713                 c[0] = r;
9714                 c[1] = g;
9715                 c[2] = b;
9716                 c[3] = f * a;
9717         }
9718 }
9719
9720 void RSurf_SetupDepthAndCulling(void)
9721 {
9722         // submodels are biased to avoid z-fighting with world surfaces that they
9723         // may be exactly overlapping (avoids z-fighting artifacts on certain
9724         // doors and things in Quake maps)
9725         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9726         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9727         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9728         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9729 }
9730
9731 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9732 {
9733         // transparent sky would be ridiculous
9734         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9735                 return;
9736         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9737         skyrenderlater = true;
9738         RSurf_SetupDepthAndCulling();
9739         GL_DepthMask(true);
9740         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9741         // skymasking on them, and Quake3 never did sky masking (unlike
9742         // software Quake and software Quake2), so disable the sky masking
9743         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9744         // and skymasking also looks very bad when noclipping outside the
9745         // level, so don't use it then either.
9746         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9747         {
9748                 R_Mesh_ResetTextureState();
9749                 if (skyrendermasked)
9750                 {
9751                         R_SetupShader_DepthOrShadow(false);
9752                         // depth-only (masking)
9753                         GL_ColorMask(0,0,0,0);
9754                         // just to make sure that braindead drivers don't draw
9755                         // anything despite that colormask...
9756                         GL_BlendFunc(GL_ZERO, GL_ONE);
9757                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9758                         if (rsurface.batchvertex3fbuffer)
9759                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9760                         else
9761                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9762                 }
9763                 else
9764                 {
9765                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9766                         // fog sky
9767                         GL_BlendFunc(GL_ONE, GL_ZERO);
9768                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9769                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9770                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9771                 }
9772                 RSurf_DrawBatch();
9773                 if (skyrendermasked)
9774                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9775         }
9776         R_Mesh_ResetTextureState();
9777         GL_Color(1, 1, 1, 1);
9778 }
9779
9780 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9781 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9782 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9783 {
9784         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9785                 return;
9786         if (prepass)
9787         {
9788                 // render screenspace normalmap to texture
9789                 GL_DepthMask(true);
9790                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9791                 RSurf_DrawBatch();
9792         }
9793
9794         // bind lightmap texture
9795
9796         // water/refraction/reflection/camera surfaces have to be handled specially
9797         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9798         {
9799                 int start, end, startplaneindex;
9800                 for (start = 0;start < texturenumsurfaces;start = end)
9801                 {
9802                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9803                         if(startplaneindex < 0)
9804                         {
9805                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9806                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9807                                 end = start + 1;
9808                                 continue;
9809                         }
9810                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9811                                 ;
9812                         // now that we have a batch using the same planeindex, render it
9813                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9814                         {
9815                                 // render water or distortion background
9816                                 GL_DepthMask(true);
9817                                 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);
9818                                 RSurf_DrawBatch();
9819                                 // blend surface on top
9820                                 GL_DepthMask(false);
9821                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9822                                 RSurf_DrawBatch();
9823                         }
9824                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9825                         {
9826                                 // render surface with reflection texture as input
9827                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9828                                 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);
9829                                 RSurf_DrawBatch();
9830                         }
9831                 }
9832                 return;
9833         }
9834
9835         // render surface batch normally
9836         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9837         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);
9838         RSurf_DrawBatch();
9839 }
9840
9841 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9842 {
9843         // OpenGL 1.3 path - anything not completely ancient
9844         qboolean applycolor;
9845         qboolean applyfog;
9846         int layerindex;
9847         const texturelayer_t *layer;
9848         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);
9849         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9850
9851         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9852         {
9853                 vec4_t layercolor;
9854                 int layertexrgbscale;
9855                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9856                 {
9857                         if (layerindex == 0)
9858                                 GL_AlphaTest(true);
9859                         else
9860                         {
9861                                 GL_AlphaTest(false);
9862                                 GL_DepthFunc(GL_EQUAL);
9863                         }
9864                 }
9865                 GL_DepthMask(layer->depthmask && writedepth);
9866                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9867                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9868                 {
9869                         layertexrgbscale = 4;
9870                         VectorScale(layer->color, 0.25f, layercolor);
9871                 }
9872                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9873                 {
9874                         layertexrgbscale = 2;
9875                         VectorScale(layer->color, 0.5f, layercolor);
9876                 }
9877                 else
9878                 {
9879                         layertexrgbscale = 1;
9880                         VectorScale(layer->color, 1.0f, layercolor);
9881                 }
9882                 layercolor[3] = layer->color[3];
9883                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9884                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9885                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9886                 switch (layer->type)
9887                 {
9888                 case TEXTURELAYERTYPE_LITTEXTURE:
9889                         // single-pass lightmapped texture with 2x rgbscale
9890                         R_Mesh_TexBind(0, r_texture_white);
9891                         R_Mesh_TexMatrix(0, NULL);
9892                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9893                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9894                         R_Mesh_TexBind(1, layer->texture);
9895                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9896                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9897                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9899                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9900                         else if (FAKELIGHT_ENABLED)
9901                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902                         else if (rsurface.uselightmaptexture)
9903                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9904                         else
9905                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9906                         break;
9907                 case TEXTURELAYERTYPE_TEXTURE:
9908                         // singletexture unlit texture with transparency support
9909                         R_Mesh_TexBind(0, layer->texture);
9910                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9911                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9912                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9913                         R_Mesh_TexBind(1, 0);
9914                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9915                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9916                         break;
9917                 case TEXTURELAYERTYPE_FOG:
9918                         // singletexture fogging
9919                         if (layer->texture)
9920                         {
9921                                 R_Mesh_TexBind(0, layer->texture);
9922                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9923                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9925                         }
9926                         else
9927                         {
9928                                 R_Mesh_TexBind(0, 0);
9929                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9930                         }
9931                         R_Mesh_TexBind(1, 0);
9932                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9933                         // generate a color array for the fog pass
9934                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9935                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9936                         RSurf_DrawBatch();
9937                         break;
9938                 default:
9939                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9940                 }
9941         }
9942         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9943         {
9944                 GL_DepthFunc(GL_LEQUAL);
9945                 GL_AlphaTest(false);
9946         }
9947 }
9948
9949 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9950 {
9951         // OpenGL 1.1 - crusty old voodoo path
9952         qboolean applyfog;
9953         int layerindex;
9954         const texturelayer_t *layer;
9955         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);
9956         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9957
9958         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9959         {
9960                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9961                 {
9962                         if (layerindex == 0)
9963                                 GL_AlphaTest(true);
9964                         else
9965                         {
9966                                 GL_AlphaTest(false);
9967                                 GL_DepthFunc(GL_EQUAL);
9968                         }
9969                 }
9970                 GL_DepthMask(layer->depthmask && writedepth);
9971                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9972                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9973                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9974                 switch (layer->type)
9975                 {
9976                 case TEXTURELAYERTYPE_LITTEXTURE:
9977                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9978                         {
9979                                 // two-pass lit texture with 2x rgbscale
9980                                 // first the lightmap pass
9981                                 R_Mesh_TexBind(0, r_texture_white);
9982                                 R_Mesh_TexMatrix(0, NULL);
9983                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9984                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9985                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9986                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9987                                 else if (FAKELIGHT_ENABLED)
9988                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9989                                 else if (rsurface.uselightmaptexture)
9990                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9991                                 else
9992                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9993                                 // then apply the texture to it
9994                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9995                                 R_Mesh_TexBind(0, layer->texture);
9996                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9997                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9998                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9999                                 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);
10000                         }
10001                         else
10002                         {
10003                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10004                                 R_Mesh_TexBind(0, layer->texture);
10005                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10006                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10007                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10008                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10009                                         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);
10010                                 else
10011                                         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);
10012                         }
10013                         break;
10014                 case TEXTURELAYERTYPE_TEXTURE:
10015                         // singletexture unlit texture with transparency support
10016                         R_Mesh_TexBind(0, layer->texture);
10017                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10018                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10019                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10020                         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);
10021                         break;
10022                 case TEXTURELAYERTYPE_FOG:
10023                         // singletexture fogging
10024                         if (layer->texture)
10025                         {
10026                                 R_Mesh_TexBind(0, layer->texture);
10027                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10028                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10029                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10030                         }
10031                         else
10032                         {
10033                                 R_Mesh_TexBind(0, 0);
10034                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10035                         }
10036                         // generate a color array for the fog pass
10037                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10038                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10039                         RSurf_DrawBatch();
10040                         break;
10041                 default:
10042                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10043                 }
10044         }
10045         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10046         {
10047                 GL_DepthFunc(GL_LEQUAL);
10048                 GL_AlphaTest(false);
10049         }
10050 }
10051
10052 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10053 {
10054         int vi;
10055         int j;
10056         r_vertexgeneric_t *batchvertex;
10057         float c[4];
10058
10059 //      R_Mesh_ResetTextureState();
10060         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10061
10062         if(rsurface.texture && rsurface.texture->currentskinframe)
10063         {
10064                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10065                 c[3] *= rsurface.texture->currentalpha;
10066         }
10067         else
10068         {
10069                 c[0] = 1;
10070                 c[1] = 0;
10071                 c[2] = 1;
10072                 c[3] = 1;
10073         }
10074
10075         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10076         {
10077                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10078                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10079                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10080         }
10081
10082         // brighten it up (as texture value 127 means "unlit")
10083         c[0] *= 2 * r_refdef.view.colorscale;
10084         c[1] *= 2 * r_refdef.view.colorscale;
10085         c[2] *= 2 * r_refdef.view.colorscale;
10086
10087         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10088                 c[3] *= r_wateralpha.value;
10089
10090         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10091         {
10092                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10093                 GL_DepthMask(false);
10094         }
10095         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10096         {
10097                 GL_BlendFunc(GL_ONE, GL_ONE);
10098                 GL_DepthMask(false);
10099         }
10100         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10101         {
10102                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10103                 GL_DepthMask(false);
10104         }
10105         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10106         {
10107                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10108                 GL_DepthMask(false);
10109         }
10110         else
10111         {
10112                 GL_BlendFunc(GL_ONE, GL_ZERO);
10113                 GL_DepthMask(writedepth);
10114         }
10115
10116         if (r_showsurfaces.integer == 3)
10117         {
10118                 rsurface.passcolor4f = NULL;
10119
10120                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10121                 {
10122                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10123
10124                         rsurface.passcolor4f = NULL;
10125                         rsurface.passcolor4f_vertexbuffer = 0;
10126                         rsurface.passcolor4f_bufferoffset = 0;
10127                 }
10128                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10129                 {
10130                         qboolean applycolor = true;
10131                         float one = 1.0;
10132
10133                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10134
10135                         r_refdef.lightmapintensity = 1;
10136                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10137                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10138                 }
10139                 else if (FAKELIGHT_ENABLED)
10140                 {
10141                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10142
10143                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10144                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10145                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10146                 }
10147                 else
10148                 {
10149                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10150
10151                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10152                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10153                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10154                 }
10155
10156                 if(!rsurface.passcolor4f)
10157                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10158
10159                 RSurf_DrawBatch_GL11_ApplyAmbient();
10160                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10161                 if(r_refdef.fogenabled)
10162                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10163                 RSurf_DrawBatch_GL11_ClampColor();
10164
10165                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10166                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10167                 RSurf_DrawBatch();
10168         }
10169         else if (!r_refdef.view.showdebug)
10170         {
10171                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10173                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10174                 {
10175                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10176                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10177                 }
10178                 R_Mesh_PrepareVertices_Generic_Unlock();
10179                 RSurf_DrawBatch();
10180         }
10181         else if (r_showsurfaces.integer == 4)
10182         {
10183                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10184                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10185                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10186                 {
10187                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10188                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10189                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10190                 }
10191                 R_Mesh_PrepareVertices_Generic_Unlock();
10192                 RSurf_DrawBatch();
10193         }
10194         else if (r_showsurfaces.integer == 2)
10195         {
10196                 const int *e;
10197                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10198                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10199                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10200                 {
10201                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10202                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10203                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10204                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10205                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10206                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10207                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10208                 }
10209                 R_Mesh_PrepareVertices_Generic_Unlock();
10210                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10211         }
10212         else
10213         {
10214                 int texturesurfaceindex;
10215                 int k;
10216                 const msurface_t *surface;
10217                 float surfacecolor4f[4];
10218                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10219                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10220                 vi = 0;
10221                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10222                 {
10223                         surface = texturesurfacelist[texturesurfaceindex];
10224                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10225                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10226                         for (j = 0;j < surface->num_vertices;j++)
10227                         {
10228                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10229                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10230                                 vi++;
10231                         }
10232                 }
10233                 R_Mesh_PrepareVertices_Generic_Unlock();
10234                 RSurf_DrawBatch();
10235         }
10236 }
10237
10238 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10239 {
10240         CHECKGLERROR
10241         RSurf_SetupDepthAndCulling();
10242         if (r_showsurfaces.integer)
10243         {
10244                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10245                 return;
10246         }
10247         switch (vid.renderpath)
10248         {
10249         case RENDERPATH_GL20:
10250         case RENDERPATH_D3D9:
10251         case RENDERPATH_D3D10:
10252         case RENDERPATH_D3D11:
10253         case RENDERPATH_SOFT:
10254         case RENDERPATH_GLES2:
10255                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10256                 break;
10257         case RENDERPATH_GL13:
10258         case RENDERPATH_GLES1:
10259                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10260                 break;
10261         case RENDERPATH_GL11:
10262                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10263                 break;
10264         }
10265         CHECKGLERROR
10266 }
10267
10268 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10269 {
10270         CHECKGLERROR
10271         RSurf_SetupDepthAndCulling();
10272         if (r_showsurfaces.integer)
10273         {
10274                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10275                 return;
10276         }
10277         switch (vid.renderpath)
10278         {
10279         case RENDERPATH_GL20:
10280         case RENDERPATH_D3D9:
10281         case RENDERPATH_D3D10:
10282         case RENDERPATH_D3D11:
10283         case RENDERPATH_SOFT:
10284         case RENDERPATH_GLES2:
10285                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10286                 break;
10287         case RENDERPATH_GL13:
10288         case RENDERPATH_GLES1:
10289                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10290                 break;
10291         case RENDERPATH_GL11:
10292                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10293                 break;
10294         }
10295         CHECKGLERROR
10296 }
10297
10298 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10299 {
10300         int i, j;
10301         int texturenumsurfaces, endsurface;
10302         texture_t *texture;
10303         const msurface_t *surface;
10304         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10305
10306         // if the model is static it doesn't matter what value we give for
10307         // wantnormals and wanttangents, so this logic uses only rules applicable
10308         // to a model, knowing that they are meaningless otherwise
10309         if (ent == r_refdef.scene.worldentity)
10310                 RSurf_ActiveWorldEntity();
10311         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10312                 RSurf_ActiveModelEntity(ent, false, false, false);
10313         else
10314         {
10315                 switch (vid.renderpath)
10316                 {
10317                 case RENDERPATH_GL20:
10318                 case RENDERPATH_D3D9:
10319                 case RENDERPATH_D3D10:
10320                 case RENDERPATH_D3D11:
10321                 case RENDERPATH_SOFT:
10322                 case RENDERPATH_GLES2:
10323                         RSurf_ActiveModelEntity(ent, true, true, false);
10324                         break;
10325                 case RENDERPATH_GL11:
10326                 case RENDERPATH_GL13:
10327                 case RENDERPATH_GLES1:
10328                         RSurf_ActiveModelEntity(ent, true, false, false);
10329                         break;
10330                 }
10331         }
10332
10333         if (r_transparentdepthmasking.integer)
10334         {
10335                 qboolean setup = false;
10336                 for (i = 0;i < numsurfaces;i = j)
10337                 {
10338                         j = i + 1;
10339                         surface = rsurface.modelsurfaces + surfacelist[i];
10340                         texture = surface->texture;
10341                         rsurface.texture = R_GetCurrentTexture(texture);
10342                         rsurface.lightmaptexture = NULL;
10343                         rsurface.deluxemaptexture = NULL;
10344                         rsurface.uselightmaptexture = false;
10345                         // scan ahead until we find a different texture
10346                         endsurface = min(i + 1024, numsurfaces);
10347                         texturenumsurfaces = 0;
10348                         texturesurfacelist[texturenumsurfaces++] = surface;
10349                         for (;j < endsurface;j++)
10350                         {
10351                                 surface = rsurface.modelsurfaces + surfacelist[j];
10352                                 if (texture != surface->texture)
10353                                         break;
10354                                 texturesurfacelist[texturenumsurfaces++] = surface;
10355                         }
10356                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10357                                 continue;
10358                         // render the range of surfaces as depth
10359                         if (!setup)
10360                         {
10361                                 setup = true;
10362                                 GL_ColorMask(0,0,0,0);
10363                                 GL_Color(1,1,1,1);
10364                                 GL_DepthTest(true);
10365                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10366                                 GL_DepthMask(true);
10367 //                              R_Mesh_ResetTextureState();
10368                                 R_SetupShader_DepthOrShadow(false);
10369                         }
10370                         RSurf_SetupDepthAndCulling();
10371                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10372                         if (rsurface.batchvertex3fbuffer)
10373                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10374                         else
10375                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10376                         RSurf_DrawBatch();
10377                 }
10378                 if (setup)
10379                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10380         }
10381
10382         for (i = 0;i < numsurfaces;i = j)
10383         {
10384                 j = i + 1;
10385                 surface = rsurface.modelsurfaces + surfacelist[i];
10386                 texture = surface->texture;
10387                 rsurface.texture = R_GetCurrentTexture(texture);
10388                 // scan ahead until we find a different texture
10389                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10390                 texturenumsurfaces = 0;
10391                 texturesurfacelist[texturenumsurfaces++] = surface;
10392                 if(FAKELIGHT_ENABLED)
10393                 {
10394                         rsurface.lightmaptexture = NULL;
10395                         rsurface.deluxemaptexture = NULL;
10396                         rsurface.uselightmaptexture = false;
10397                         for (;j < endsurface;j++)
10398                         {
10399                                 surface = rsurface.modelsurfaces + surfacelist[j];
10400                                 if (texture != surface->texture)
10401                                         break;
10402                                 texturesurfacelist[texturenumsurfaces++] = surface;
10403                         }
10404                 }
10405                 else
10406                 {
10407                         rsurface.lightmaptexture = surface->lightmaptexture;
10408                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10409                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10410                         for (;j < endsurface;j++)
10411                         {
10412                                 surface = rsurface.modelsurfaces + surfacelist[j];
10413                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10414                                         break;
10415                                 texturesurfacelist[texturenumsurfaces++] = surface;
10416                         }
10417                 }
10418                 // render the range of surfaces
10419                 if (ent == r_refdef.scene.worldentity)
10420                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10421                 else
10422                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10423         }
10424         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10425 }
10426
10427 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10428 {
10429         // transparent surfaces get pushed off into the transparent queue
10430         int surfacelistindex;
10431         const msurface_t *surface;
10432         vec3_t tempcenter, center;
10433         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10434         {
10435                 surface = texturesurfacelist[surfacelistindex];
10436                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10437                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10438                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10439                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10440                 if (queueentity->transparent_offset) // transparent offset
10441                 {
10442                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10443                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10444                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10445                 }
10446                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10447         }
10448 }
10449
10450 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10451 {
10452         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10453                 return;
10454         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10455                 return;
10456         RSurf_SetupDepthAndCulling();
10457         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10458         if (rsurface.batchvertex3fbuffer)
10459                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10460         else
10461                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10462         RSurf_DrawBatch();
10463 }
10464
10465 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10466 {
10467         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10468         CHECKGLERROR
10469         if (depthonly)
10470                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10471         else if (prepass)
10472         {
10473                 if (!rsurface.texture->currentnumlayers)
10474                         return;
10475                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10476                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10477                 else
10478                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10479         }
10480         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10481                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10482         else if (!rsurface.texture->currentnumlayers)
10483                 return;
10484         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10485         {
10486                 // in the deferred case, transparent surfaces were queued during prepass
10487                 if (!r_shadow_usingdeferredprepass)
10488                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10489         }
10490         else
10491         {
10492                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10493                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10494         }
10495         CHECKGLERROR
10496 }
10497
10498 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10499 {
10500         int i, j;
10501         texture_t *texture;
10502         R_FrameData_SetMark();
10503         // break the surface list down into batches by texture and use of lightmapping
10504         for (i = 0;i < numsurfaces;i = j)
10505         {
10506                 j = i + 1;
10507                 // texture is the base texture pointer, rsurface.texture is the
10508                 // current frame/skin the texture is directing us to use (for example
10509                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10510                 // use skin 1 instead)
10511                 texture = surfacelist[i]->texture;
10512                 rsurface.texture = R_GetCurrentTexture(texture);
10513                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10514                 {
10515                         // if this texture is not the kind we want, skip ahead to the next one
10516                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10517                                 ;
10518                         continue;
10519                 }
10520                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10521                 {
10522                         rsurface.lightmaptexture = NULL;
10523                         rsurface.deluxemaptexture = NULL;
10524                         rsurface.uselightmaptexture = false;
10525                         // simply scan ahead until we find a different texture or lightmap state
10526                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10527                                 ;
10528                 }
10529                 else
10530                 {
10531                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10532                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10533                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10534                         // simply scan ahead until we find a different texture or lightmap state
10535                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10536                                 ;
10537                 }
10538                 // render the range of surfaces
10539                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10540         }
10541         R_FrameData_ReturnToMark();
10542 }
10543
10544 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10545 {
10546         CHECKGLERROR
10547         if (depthonly)
10548                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10549         else if (prepass)
10550         {
10551                 if (!rsurface.texture->currentnumlayers)
10552                         return;
10553                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10554                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10555                 else
10556                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10557         }
10558         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10559                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10560         else if (!rsurface.texture->currentnumlayers)
10561                 return;
10562         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10563         {
10564                 // in the deferred case, transparent surfaces were queued during prepass
10565                 if (!r_shadow_usingdeferredprepass)
10566                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10567         }
10568         else
10569         {
10570                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10571                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10572         }
10573         CHECKGLERROR
10574 }
10575
10576 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10577 {
10578         int i, j;
10579         texture_t *texture;
10580         R_FrameData_SetMark();
10581         // break the surface list down into batches by texture and use of lightmapping
10582         for (i = 0;i < numsurfaces;i = j)
10583         {
10584                 j = i + 1;
10585                 // texture is the base texture pointer, rsurface.texture is the
10586                 // current frame/skin the texture is directing us to use (for example
10587                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10588                 // use skin 1 instead)
10589                 texture = surfacelist[i]->texture;
10590                 rsurface.texture = R_GetCurrentTexture(texture);
10591                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10592                 {
10593                         // if this texture is not the kind we want, skip ahead to the next one
10594                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10595                                 ;
10596                         continue;
10597                 }
10598                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10599                 {
10600                         rsurface.lightmaptexture = NULL;
10601                         rsurface.deluxemaptexture = NULL;
10602                         rsurface.uselightmaptexture = false;
10603                         // simply scan ahead until we find a different texture or lightmap state
10604                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10605                                 ;
10606                 }
10607                 else
10608                 {
10609                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10610                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10611                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10612                         // simply scan ahead until we find a different texture or lightmap state
10613                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10614                                 ;
10615                 }
10616                 // render the range of surfaces
10617                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10618         }
10619         R_FrameData_ReturnToMark();
10620 }
10621
10622 float locboxvertex3f[6*4*3] =
10623 {
10624         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10625         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10626         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10627         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10628         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10629         1,0,0, 0,0,0, 0,1,0, 1,1,0
10630 };
10631
10632 unsigned short locboxelements[6*2*3] =
10633 {
10634          0, 1, 2, 0, 2, 3,
10635          4, 5, 6, 4, 6, 7,
10636          8, 9,10, 8,10,11,
10637         12,13,14, 12,14,15,
10638         16,17,18, 16,18,19,
10639         20,21,22, 20,22,23
10640 };
10641
10642 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10643 {
10644         int i, j;
10645         cl_locnode_t *loc = (cl_locnode_t *)ent;
10646         vec3_t mins, size;
10647         float vertex3f[6*4*3];
10648         CHECKGLERROR
10649         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10650         GL_DepthMask(false);
10651         GL_DepthRange(0, 1);
10652         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10653         GL_DepthTest(true);
10654         GL_CullFace(GL_NONE);
10655         R_EntityMatrix(&identitymatrix);
10656
10657 //      R_Mesh_ResetTextureState();
10658
10659         i = surfacelist[0];
10660         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10661                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10662                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10663                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10664
10665         if (VectorCompare(loc->mins, loc->maxs))
10666         {
10667                 VectorSet(size, 2, 2, 2);
10668                 VectorMA(loc->mins, -0.5f, size, mins);
10669         }
10670         else
10671         {
10672                 VectorCopy(loc->mins, mins);
10673                 VectorSubtract(loc->maxs, loc->mins, size);
10674         }
10675
10676         for (i = 0;i < 6*4*3;)
10677                 for (j = 0;j < 3;j++, i++)
10678                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10679
10680         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10681         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10682         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10683 }
10684
10685 void R_DrawLocs(void)
10686 {
10687         int index;
10688         cl_locnode_t *loc, *nearestloc;
10689         vec3_t center;
10690         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10691         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10692         {
10693                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10694                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10695         }
10696 }
10697
10698 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10699 {
10700         if (decalsystem->decals)
10701                 Mem_Free(decalsystem->decals);
10702         memset(decalsystem, 0, sizeof(*decalsystem));
10703 }
10704
10705 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
10706 {
10707         tridecal_t *decal;
10708         tridecal_t *decals;
10709         int i;
10710
10711         // expand or initialize the system
10712         if (decalsystem->maxdecals <= decalsystem->numdecals)
10713         {
10714                 decalsystem_t old = *decalsystem;
10715                 qboolean useshortelements;
10716                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10717                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10718                 decalsystem->decals = (tridecal_t *)Mem_Alloc(cls.levelmempool, decalsystem->maxdecals * (sizeof(tridecal_t) + sizeof(float[3][3]) + sizeof(float[3][2]) + sizeof(float[3][4]) + sizeof(int[3]) + (useshortelements ? sizeof(unsigned short[3]) : 0)));
10719                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10720                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10721                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10722                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10723                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10724                 if (decalsystem->numdecals)
10725                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10726                 if (old.decals)
10727                         Mem_Free(old.decals);
10728                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10729                         decalsystem->element3i[i] = i;
10730                 if (useshortelements)
10731                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10732                                 decalsystem->element3s[i] = i;
10733         }
10734
10735         // grab a decal and search for another free slot for the next one
10736         decals = decalsystem->decals;
10737         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10738         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10739                 ;
10740         decalsystem->freedecal = i;
10741         if (decalsystem->numdecals <= i)
10742                 decalsystem->numdecals = i + 1;
10743
10744         // initialize the decal
10745         decal->lived = 0;
10746         decal->triangleindex = triangleindex;
10747         decal->surfaceindex = surfaceindex;
10748         decal->decalsequence = decalsequence;
10749         decal->color4f[0][0] = c0[0];
10750         decal->color4f[0][1] = c0[1];
10751         decal->color4f[0][2] = c0[2];
10752         decal->color4f[0][3] = 1;
10753         decal->color4f[1][0] = c1[0];
10754         decal->color4f[1][1] = c1[1];
10755         decal->color4f[1][2] = c1[2];
10756         decal->color4f[1][3] = 1;
10757         decal->color4f[2][0] = c2[0];
10758         decal->color4f[2][1] = c2[1];
10759         decal->color4f[2][2] = c2[2];
10760         decal->color4f[2][3] = 1;
10761         decal->vertex3f[0][0] = v0[0];
10762         decal->vertex3f[0][1] = v0[1];
10763         decal->vertex3f[0][2] = v0[2];
10764         decal->vertex3f[1][0] = v1[0];
10765         decal->vertex3f[1][1] = v1[1];
10766         decal->vertex3f[1][2] = v1[2];
10767         decal->vertex3f[2][0] = v2[0];
10768         decal->vertex3f[2][1] = v2[1];
10769         decal->vertex3f[2][2] = v2[2];
10770         decal->texcoord2f[0][0] = t0[0];
10771         decal->texcoord2f[0][1] = t0[1];
10772         decal->texcoord2f[1][0] = t1[0];
10773         decal->texcoord2f[1][1] = t1[1];
10774         decal->texcoord2f[2][0] = t2[0];
10775         decal->texcoord2f[2][1] = t2[1];
10776         TriangleNormal(v0, v1, v2, decal->plane);
10777         VectorNormalize(decal->plane);
10778         decal->plane[3] = DotProduct(v0, decal->plane);
10779 }
10780
10781 extern cvar_t cl_decals_bias;
10782 extern cvar_t cl_decals_models;
10783 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10784 // baseparms, parms, temps
10785 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
10786 {
10787         int cornerindex;
10788         int index;
10789         float v[9][3];
10790         const float *vertex3f;
10791         const float *normal3f;
10792         int numpoints;
10793         float points[2][9][3];
10794         float temp[3];
10795         float tc[9][2];
10796         float f;
10797         float c[9][4];
10798         const int *e;
10799
10800         e = rsurface.modelelement3i + 3*triangleindex;
10801
10802         vertex3f = rsurface.modelvertex3f;
10803         normal3f = rsurface.modelnormal3f;
10804
10805         if (normal3f)
10806         {
10807                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10808                 {
10809                         index = 3*e[cornerindex];
10810                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10811                 }
10812         }
10813         else
10814         {
10815                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10816                 {
10817                         index = 3*e[cornerindex];
10818                         VectorCopy(vertex3f + index, v[cornerindex]);
10819                 }
10820         }
10821
10822         // cull backfaces
10823         //TriangleNormal(v[0], v[1], v[2], normal);
10824         //if (DotProduct(normal, localnormal) < 0.0f)
10825         //      continue;
10826         // clip by each of the box planes formed from the projection matrix
10827         // if anything survives, we emit the decal
10828         numpoints = PolygonF_Clip(3        , v[0]        , planes[0][0], planes[0][1], planes[0][2], planes[0][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10829         if (numpoints < 3)
10830                 return;
10831         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[1][0], planes[1][1], planes[1][2], planes[1][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10832         if (numpoints < 3)
10833                 return;
10834         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[2][0], planes[2][1], planes[2][2], planes[2][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10835         if (numpoints < 3)
10836                 return;
10837         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[3][0], planes[3][1], planes[3][2], planes[3][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[0][0]);
10838         if (numpoints < 3)
10839                 return;
10840         numpoints = PolygonF_Clip(numpoints, points[0][0], planes[4][0], planes[4][1], planes[4][2], planes[4][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), points[1][0]);
10841         if (numpoints < 3)
10842                 return;
10843         numpoints = PolygonF_Clip(numpoints, points[1][0], planes[5][0], planes[5][1], planes[5][2], planes[5][3], 1.0f/64.0f, sizeof(points[0])/sizeof(points[0][0]), v[0]);
10844         if (numpoints < 3)
10845                 return;
10846         // some part of the triangle survived, so we have to accept it...
10847         if (dynamic)
10848         {
10849                 // dynamic always uses the original triangle
10850                 numpoints = 3;
10851                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10852                 {
10853                         index = 3*e[cornerindex];
10854                         VectorCopy(vertex3f + index, v[cornerindex]);
10855                 }
10856         }
10857         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10858         {
10859                 // convert vertex positions to texcoords
10860                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10861                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10862                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10863                 // calculate distance fade from the projection origin
10864                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10865                 f = bound(0.0f, f, 1.0f);
10866                 c[cornerindex][0] = r * f;
10867                 c[cornerindex][1] = g * f;
10868                 c[cornerindex][2] = b * f;
10869                 c[cornerindex][3] = 1.0f;
10870                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10871         }
10872         if (dynamic)
10873                 R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[1], v[2], tc[0], tc[1], tc[2], c[0], c[1], c[2], triangleindex, surfaceindex, decalsequence);
10874         else
10875                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10876                         R_DecalSystem_SpawnTriangle(decalsystem, v[0], v[cornerindex+1], v[cornerindex+2], tc[0], tc[cornerindex+1], tc[cornerindex+2], c[0], c[cornerindex+1], c[cornerindex+2], -1, surfaceindex, decalsequence);
10877 }
10878 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
10879 {
10880         matrix4x4_t projection;
10881         decalsystem_t *decalsystem;
10882         qboolean dynamic;
10883         dp_model_t *model;
10884         const msurface_t *surface;
10885         const msurface_t *surfaces;
10886         const int *surfacelist;
10887         const texture_t *texture;
10888         int numtriangles;
10889         int numsurfacelist;
10890         int surfacelistindex;
10891         int surfaceindex;
10892         int triangleindex;
10893         float localorigin[3];
10894         float localnormal[3];
10895         float localmins[3];
10896         float localmaxs[3];
10897         float localsize;
10898         //float normal[3];
10899         float planes[6][4];
10900         float angles[3];
10901         bih_t *bih;
10902         int bih_triangles_count;
10903         int bih_triangles[256];
10904         int bih_surfaces[256];
10905
10906         decalsystem = &ent->decalsystem;
10907         model = ent->model;
10908         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10909         {
10910                 R_DecalSystem_Reset(&ent->decalsystem);
10911                 return;
10912         }
10913
10914         if (!model->brush.data_leafs && !cl_decals_models.integer)
10915         {
10916                 if (decalsystem->model)
10917                         R_DecalSystem_Reset(decalsystem);
10918                 return;
10919         }
10920
10921         if (decalsystem->model != model)
10922                 R_DecalSystem_Reset(decalsystem);
10923         decalsystem->model = model;
10924
10925         RSurf_ActiveModelEntity(ent, true, false, false);
10926
10927         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10928         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10929         VectorNormalize(localnormal);
10930         localsize = worldsize*rsurface.inversematrixscale;
10931         localmins[0] = localorigin[0] - localsize;
10932         localmins[1] = localorigin[1] - localsize;
10933         localmins[2] = localorigin[2] - localsize;
10934         localmaxs[0] = localorigin[0] + localsize;
10935         localmaxs[1] = localorigin[1] + localsize;
10936         localmaxs[2] = localorigin[2] + localsize;
10937
10938         //VectorCopy(localnormal, planes[4]);
10939         //VectorVectors(planes[4], planes[2], planes[0]);
10940         AnglesFromVectors(angles, localnormal, NULL, false);
10941         AngleVectors(angles, planes[0], planes[2], planes[4]);
10942         VectorNegate(planes[0], planes[1]);
10943         VectorNegate(planes[2], planes[3]);
10944         VectorNegate(planes[4], planes[5]);
10945         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10946         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10947         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10948         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10949         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10950         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10951
10952 #if 1
10953 // works
10954 {
10955         matrix4x4_t forwardprojection;
10956         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10957         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10958 }
10959 #else
10960 // broken
10961 {
10962         float projectionvector[4][3];
10963         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10964         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10965         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10966         projectionvector[0][0] = planes[0][0] * ilocalsize;
10967         projectionvector[0][1] = planes[1][0] * ilocalsize;
10968         projectionvector[0][2] = planes[2][0] * ilocalsize;
10969         projectionvector[1][0] = planes[0][1] * ilocalsize;
10970         projectionvector[1][1] = planes[1][1] * ilocalsize;
10971         projectionvector[1][2] = planes[2][1] * ilocalsize;
10972         projectionvector[2][0] = planes[0][2] * ilocalsize;
10973         projectionvector[2][1] = planes[1][2] * ilocalsize;
10974         projectionvector[2][2] = planes[2][2] * ilocalsize;
10975         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10976         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10977         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10978         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10979 }
10980 #endif
10981
10982         dynamic = model->surfmesh.isanimated;
10983         numsurfacelist = model->nummodelsurfaces;
10984         surfacelist = model->sortedmodelsurfaces;
10985         surfaces = model->data_surfaces;
10986
10987         bih = NULL;
10988         bih_triangles_count = -1;
10989         if(!dynamic)
10990         {
10991                 if(model->render_bih.numleafs)
10992                         bih = &model->render_bih;
10993                 else if(model->collision_bih.numleafs)
10994                         bih = &model->collision_bih;
10995         }
10996         if(bih)
10997                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10998         if(bih_triangles_count == 0)
10999                 return;
11000         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11001                 return;
11002         if(bih_triangles_count > 0)
11003         {
11004                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11005                 {
11006                         surfaceindex = bih_surfaces[triangleindex];
11007                         surface = surfaces + surfaceindex;
11008                         texture = surface->texture;
11009                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11010                                 continue;
11011                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11012                                 continue;
11013                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11014                 }
11015         }
11016         else
11017         {
11018                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11019                 {
11020                         surfaceindex = surfacelist[surfacelistindex];
11021                         surface = surfaces + surfaceindex;
11022                         // check cull box first because it rejects more than any other check
11023                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11024                                 continue;
11025                         // skip transparent surfaces
11026                         texture = surface->texture;
11027                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11028                                 continue;
11029                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11030                                 continue;
11031                         numtriangles = surface->num_triangles;
11032                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11033                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11034                 }
11035         }
11036 }
11037
11038 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11039 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11040 {
11041         int renderentityindex;
11042         float worldmins[3];
11043         float worldmaxs[3];
11044         entity_render_t *ent;
11045
11046         if (!cl_decals_newsystem.integer)
11047                 return;
11048
11049         worldmins[0] = worldorigin[0] - worldsize;
11050         worldmins[1] = worldorigin[1] - worldsize;
11051         worldmins[2] = worldorigin[2] - worldsize;
11052         worldmaxs[0] = worldorigin[0] + worldsize;
11053         worldmaxs[1] = worldorigin[1] + worldsize;
11054         worldmaxs[2] = worldorigin[2] + worldsize;
11055
11056         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11057
11058         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11059         {
11060                 ent = r_refdef.scene.entities[renderentityindex];
11061                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11062                         continue;
11063
11064                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11065         }
11066 }
11067
11068 typedef struct r_decalsystem_splatqueue_s
11069 {
11070         vec3_t worldorigin;
11071         vec3_t worldnormal;
11072         float color[4];
11073         float tcrange[4];
11074         float worldsize;
11075         int decalsequence;
11076 }
11077 r_decalsystem_splatqueue_t;
11078
11079 int r_decalsystem_numqueued = 0;
11080 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11081
11082 void R_DecalSystem_SplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize)
11083 {
11084         r_decalsystem_splatqueue_t *queue;
11085
11086         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11087                 return;
11088
11089         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11090         VectorCopy(worldorigin, queue->worldorigin);
11091         VectorCopy(worldnormal, queue->worldnormal);
11092         Vector4Set(queue->color, r, g, b, a);
11093         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11094         queue->worldsize = worldsize;
11095         queue->decalsequence = cl.decalsequence++;
11096 }
11097
11098 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11099 {
11100         int i;
11101         r_decalsystem_splatqueue_t *queue;
11102
11103         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11104                 R_DecalSystem_ApplySplatEntities(queue->worldorigin, queue->worldnormal, queue->color[0], queue->color[1], queue->color[2], queue->color[3], queue->tcrange[0], queue->tcrange[1], queue->tcrange[2], queue->tcrange[3], queue->worldsize, queue->decalsequence);
11105         r_decalsystem_numqueued = 0;
11106 }
11107
11108 extern cvar_t cl_decals_max;
11109 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11110 {
11111         int i;
11112         decalsystem_t *decalsystem = &ent->decalsystem;
11113         int numdecals;
11114         int killsequence;
11115         tridecal_t *decal;
11116         float frametime;
11117         float lifetime;
11118
11119         if (!decalsystem->numdecals)
11120                 return;
11121
11122         if (r_showsurfaces.integer)
11123                 return;
11124
11125         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11126         {
11127                 R_DecalSystem_Reset(decalsystem);
11128                 return;
11129         }
11130
11131         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11132         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11133
11134         if (decalsystem->lastupdatetime)
11135                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11136         else
11137                 frametime = 0;
11138         decalsystem->lastupdatetime = r_refdef.scene.time;
11139         decal = decalsystem->decals;
11140         numdecals = decalsystem->numdecals;
11141
11142         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11143         {
11144                 if (decal->color4f[0][3])
11145                 {
11146                         decal->lived += frametime;
11147                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11148                         {
11149                                 memset(decal, 0, sizeof(*decal));
11150                                 if (decalsystem->freedecal > i)
11151                                         decalsystem->freedecal = i;
11152                         }
11153                 }
11154         }
11155         decal = decalsystem->decals;
11156         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11157                 numdecals--;
11158
11159         // collapse the array by shuffling the tail decals into the gaps
11160         for (;;)
11161         {
11162                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11163                         decalsystem->freedecal++;
11164                 if (decalsystem->freedecal == numdecals)
11165                         break;
11166                 decal[decalsystem->freedecal] = decal[--numdecals];
11167         }
11168
11169         decalsystem->numdecals = numdecals;
11170
11171         if (numdecals <= 0)
11172         {
11173                 // if there are no decals left, reset decalsystem
11174                 R_DecalSystem_Reset(decalsystem);
11175         }
11176 }
11177
11178 extern skinframe_t *decalskinframe;
11179 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11180 {
11181         int i;
11182         decalsystem_t *decalsystem = &ent->decalsystem;
11183         int numdecals;
11184         tridecal_t *decal;
11185         float faderate;
11186         float alpha;
11187         float *v3f;
11188         float *c4f;
11189         float *t2f;
11190         const int *e;
11191         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11192         int numtris = 0;
11193
11194         numdecals = decalsystem->numdecals;
11195         if (!numdecals)
11196                 return;
11197
11198         if (r_showsurfaces.integer)
11199                 return;
11200
11201         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11202         {
11203                 R_DecalSystem_Reset(decalsystem);
11204                 return;
11205         }
11206
11207         // if the model is static it doesn't matter what value we give for
11208         // wantnormals and wanttangents, so this logic uses only rules applicable
11209         // to a model, knowing that they are meaningless otherwise
11210         if (ent == r_refdef.scene.worldentity)
11211                 RSurf_ActiveWorldEntity();
11212         else
11213                 RSurf_ActiveModelEntity(ent, false, false, false);
11214
11215         decalsystem->lastupdatetime = r_refdef.scene.time;
11216         decal = decalsystem->decals;
11217
11218         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11219
11220         // update vertex positions for animated models
11221         v3f = decalsystem->vertex3f;
11222         c4f = decalsystem->color4f;
11223         t2f = decalsystem->texcoord2f;
11224         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11225         {
11226                 if (!decal->color4f[0][3])
11227                         continue;
11228
11229                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11230                         continue;
11231
11232                 // skip backfaces
11233                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11234                         continue;
11235
11236                 // update color values for fading decals
11237                 if (decal->lived >= cl_decals_time.value)
11238                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11239                 else
11240                         alpha = 1.0f;
11241
11242                 c4f[ 0] = decal->color4f[0][0] * alpha;
11243                 c4f[ 1] = decal->color4f[0][1] * alpha;
11244                 c4f[ 2] = decal->color4f[0][2] * alpha;
11245                 c4f[ 3] = 1;
11246                 c4f[ 4] = decal->color4f[1][0] * alpha;
11247                 c4f[ 5] = decal->color4f[1][1] * alpha;
11248                 c4f[ 6] = decal->color4f[1][2] * alpha;
11249                 c4f[ 7] = 1;
11250                 c4f[ 8] = decal->color4f[2][0] * alpha;
11251                 c4f[ 9] = decal->color4f[2][1] * alpha;
11252                 c4f[10] = decal->color4f[2][2] * alpha;
11253                 c4f[11] = 1;
11254
11255                 t2f[0] = decal->texcoord2f[0][0];
11256                 t2f[1] = decal->texcoord2f[0][1];
11257                 t2f[2] = decal->texcoord2f[1][0];
11258                 t2f[3] = decal->texcoord2f[1][1];
11259                 t2f[4] = decal->texcoord2f[2][0];
11260                 t2f[5] = decal->texcoord2f[2][1];
11261
11262                 // update vertex positions for animated models
11263                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11264                 {
11265                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11266                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11267                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11268                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11269                 }
11270                 else
11271                 {
11272                         VectorCopy(decal->vertex3f[0], v3f);
11273                         VectorCopy(decal->vertex3f[1], v3f + 3);
11274                         VectorCopy(decal->vertex3f[2], v3f + 6);
11275                 }
11276
11277                 if (r_refdef.fogenabled)
11278                 {
11279                         alpha = RSurf_FogVertex(v3f);
11280                         VectorScale(c4f, alpha, c4f);
11281                         alpha = RSurf_FogVertex(v3f + 3);
11282                         VectorScale(c4f + 4, alpha, c4f + 4);
11283                         alpha = RSurf_FogVertex(v3f + 6);
11284                         VectorScale(c4f + 8, alpha, c4f + 8);
11285                 }
11286
11287                 v3f += 9;
11288                 c4f += 12;
11289                 t2f += 6;
11290                 numtris++;
11291         }
11292
11293         if (numtris > 0)
11294         {
11295                 r_refdef.stats.drawndecals += numtris;
11296
11297                 // now render the decals all at once
11298                 // (this assumes they all use one particle font texture!)
11299                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11300 //              R_Mesh_ResetTextureState();
11301                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11302                 GL_DepthMask(false);
11303                 GL_DepthRange(0, 1);
11304                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11305                 GL_DepthTest(true);
11306                 GL_CullFace(GL_NONE);
11307                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11308                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11309                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11310         }
11311 }
11312
11313 static void R_DrawModelDecals(void)
11314 {
11315         int i, numdecals;
11316
11317         // fade faster when there are too many decals
11318         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11319         for (i = 0;i < r_refdef.scene.numentities;i++)
11320                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11321
11322         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11323         for (i = 0;i < r_refdef.scene.numentities;i++)
11324                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11325                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11326
11327         R_DecalSystem_ApplySplatEntitiesQueue();
11328
11329         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11330         for (i = 0;i < r_refdef.scene.numentities;i++)
11331                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11332
11333         r_refdef.stats.totaldecals += numdecals;
11334
11335         if (r_showsurfaces.integer)
11336                 return;
11337
11338         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11339
11340         for (i = 0;i < r_refdef.scene.numentities;i++)
11341         {
11342                 if (!r_refdef.viewcache.entityvisible[i])
11343                         continue;
11344                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11345                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11346         }
11347 }
11348
11349 extern cvar_t mod_collision_bih;
11350 void R_DrawDebugModel(void)
11351 {
11352         entity_render_t *ent = rsurface.entity;
11353         int i, j, k, l, flagsmask;
11354         const msurface_t *surface;
11355         dp_model_t *model = ent->model;
11356         vec3_t v;
11357
11358         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11359                 return;
11360
11361         if (r_showoverdraw.value > 0)
11362         {
11363                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11364                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11365                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11366                 GL_DepthTest(false);
11367                 GL_DepthMask(false);
11368                 GL_DepthRange(0, 1);
11369                 GL_BlendFunc(GL_ONE, GL_ONE);
11370                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11371                 {
11372                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11373                                 continue;
11374                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11375                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11376                         {
11377                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11378                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11379                                 if (!rsurface.texture->currentlayers->depthmask)
11380                                         GL_Color(c, 0, 0, 1.0f);
11381                                 else if (ent == r_refdef.scene.worldentity)
11382                                         GL_Color(c, c, c, 1.0f);
11383                                 else
11384                                         GL_Color(0, c, 0, 1.0f);
11385                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11386                                 RSurf_DrawBatch();
11387                         }
11388                 }
11389                 rsurface.texture = NULL;
11390         }
11391
11392         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11393
11394 //      R_Mesh_ResetTextureState();
11395         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11396         GL_DepthRange(0, 1);
11397         GL_DepthTest(!r_showdisabledepthtest.integer);
11398         GL_DepthMask(false);
11399         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11400
11401         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11402         {
11403                 int triangleindex;
11404                 int bihleafindex;
11405                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11406                 const q3mbrush_t *brush;
11407                 const bih_t *bih = &model->collision_bih;
11408                 const bih_leaf_t *bihleaf;
11409                 float vertex3f[3][3];
11410                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11411                 cullbox = false;
11412                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11413                 {
11414                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11415                                 continue;
11416                         switch (bihleaf->type)
11417                         {
11418                         case BIH_BRUSH:
11419                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11420                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11421                                 {
11422                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11423                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11424                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11425                                 }
11426                                 break;
11427                         case BIH_COLLISIONTRIANGLE:
11428                                 triangleindex = bihleaf->itemindex;
11429                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11430                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11431                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11432                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11433                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11434                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11435                                 break;
11436                         case BIH_RENDERTRIANGLE:
11437                                 triangleindex = bihleaf->itemindex;
11438                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11439                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11440                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11441                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11442                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11443                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11444                                 break;
11445                         }
11446                 }
11447         }
11448
11449         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11450
11451 #ifndef USE_GLES2
11452         if (r_showtris.integer && qglPolygonMode)
11453         {
11454                 if (r_showdisabledepthtest.integer)
11455                 {
11456                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11457                         GL_DepthMask(false);
11458                 }
11459                 else
11460                 {
11461                         GL_BlendFunc(GL_ONE, GL_ZERO);
11462                         GL_DepthMask(true);
11463                 }
11464                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11465                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11466                 {
11467                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11468                                 continue;
11469                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11470                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11471                         {
11472                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11473                                 if (!rsurface.texture->currentlayers->depthmask)
11474                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11475                                 else if (ent == r_refdef.scene.worldentity)
11476                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11477                                 else
11478                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11479                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11480                                 RSurf_DrawBatch();
11481                         }
11482                 }
11483                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11484                 rsurface.texture = NULL;
11485         }
11486
11487         if (r_shownormals.value != 0 && qglBegin)
11488         {
11489                 if (r_showdisabledepthtest.integer)
11490                 {
11491                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11492                         GL_DepthMask(false);
11493                 }
11494                 else
11495                 {
11496                         GL_BlendFunc(GL_ONE, GL_ZERO);
11497                         GL_DepthMask(true);
11498                 }
11499                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11500                 {
11501                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11502                                 continue;
11503                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11504                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11505                         {
11506                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11507                                 qglBegin(GL_LINES);
11508                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11509                                 {
11510                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11511                                         {
11512                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11513                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11514                                                 qglVertex3f(v[0], v[1], v[2]);
11515                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11516                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11517                                                 qglVertex3f(v[0], v[1], v[2]);
11518                                         }
11519                                 }
11520                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11521                                 {
11522                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11523                                         {
11524                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11525                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11526                                                 qglVertex3f(v[0], v[1], v[2]);
11527                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11528                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11529                                                 qglVertex3f(v[0], v[1], v[2]);
11530                                         }
11531                                 }
11532                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11533                                 {
11534                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11535                                         {
11536                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11537                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11538                                                 qglVertex3f(v[0], v[1], v[2]);
11539                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11540                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11541                                                 qglVertex3f(v[0], v[1], v[2]);
11542                                         }
11543                                 }
11544                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11545                                 {
11546                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11547                                         {
11548                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11549                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11550                                                 qglVertex3f(v[0], v[1], v[2]);
11551                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11552                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11553                                                 qglVertex3f(v[0], v[1], v[2]);
11554                                         }
11555                                 }
11556                                 qglEnd();
11557                                 CHECKGLERROR
11558                         }
11559                 }
11560                 rsurface.texture = NULL;
11561         }
11562 #endif
11563 }
11564
11565 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11566 int r_maxsurfacelist = 0;
11567 const msurface_t **r_surfacelist = NULL;
11568 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11569 {
11570         int i, j, endj, flagsmask;
11571         dp_model_t *model = r_refdef.scene.worldmodel;
11572         msurface_t *surfaces;
11573         unsigned char *update;
11574         int numsurfacelist = 0;
11575         if (model == NULL)
11576                 return;
11577
11578         if (r_maxsurfacelist < model->num_surfaces)
11579         {
11580                 r_maxsurfacelist = model->num_surfaces;
11581                 if (r_surfacelist)
11582                         Mem_Free((msurface_t**)r_surfacelist);
11583                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11584         }
11585
11586         RSurf_ActiveWorldEntity();
11587
11588         surfaces = model->data_surfaces;
11589         update = model->brushq1.lightmapupdateflags;
11590
11591         // update light styles on this submodel
11592         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11593         {
11594                 model_brush_lightstyleinfo_t *style;
11595                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11596                 {
11597                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11598                         {
11599                                 int *list = style->surfacelist;
11600                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11601                                 for (j = 0;j < style->numsurfaces;j++)
11602                                         update[list[j]] = true;
11603                         }
11604                 }
11605         }
11606
11607         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11608
11609         if (debug)
11610         {
11611                 R_DrawDebugModel();
11612                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11613                 return;
11614         }
11615
11616         rsurface.lightmaptexture = NULL;
11617         rsurface.deluxemaptexture = NULL;
11618         rsurface.uselightmaptexture = false;
11619         rsurface.texture = NULL;
11620         rsurface.rtlight = NULL;
11621         numsurfacelist = 0;
11622         // add visible surfaces to draw list
11623         for (i = 0;i < model->nummodelsurfaces;i++)
11624         {
11625                 j = model->sortedmodelsurfaces[i];
11626                 if (r_refdef.viewcache.world_surfacevisible[j])
11627                         r_surfacelist[numsurfacelist++] = surfaces + j;
11628         }
11629         // update lightmaps if needed
11630         if (model->brushq1.firstrender)
11631         {
11632                 model->brushq1.firstrender = false;
11633                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11634                         if (update[j])
11635                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11636         }
11637         else if (update)
11638         {
11639                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11640                         if (r_refdef.viewcache.world_surfacevisible[j])
11641                                 if (update[j])
11642                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11643         }
11644         // don't do anything if there were no surfaces
11645         if (!numsurfacelist)
11646         {
11647                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11648                 return;
11649         }
11650         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11651
11652         // add to stats if desired
11653         if (r_speeds.integer && !skysurfaces && !depthonly)
11654         {
11655                 r_refdef.stats.world_surfaces += numsurfacelist;
11656                 for (j = 0;j < numsurfacelist;j++)
11657                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11658         }
11659
11660         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11661 }
11662
11663 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11664 {
11665         int i, j, endj, flagsmask;
11666         dp_model_t *model = ent->model;
11667         msurface_t *surfaces;
11668         unsigned char *update;
11669         int numsurfacelist = 0;
11670         if (model == NULL)
11671                 return;
11672
11673         if (r_maxsurfacelist < model->num_surfaces)
11674         {
11675                 r_maxsurfacelist = model->num_surfaces;
11676                 if (r_surfacelist)
11677                         Mem_Free((msurface_t **)r_surfacelist);
11678                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11679         }
11680
11681         // if the model is static it doesn't matter what value we give for
11682         // wantnormals and wanttangents, so this logic uses only rules applicable
11683         // to a model, knowing that they are meaningless otherwise
11684         if (ent == r_refdef.scene.worldentity)
11685                 RSurf_ActiveWorldEntity();
11686         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11687                 RSurf_ActiveModelEntity(ent, false, false, false);
11688         else if (prepass)
11689                 RSurf_ActiveModelEntity(ent, true, true, true);
11690         else if (depthonly)
11691         {
11692                 switch (vid.renderpath)
11693                 {
11694                 case RENDERPATH_GL20:
11695                 case RENDERPATH_D3D9:
11696                 case RENDERPATH_D3D10:
11697                 case RENDERPATH_D3D11:
11698                 case RENDERPATH_SOFT:
11699                 case RENDERPATH_GLES2:
11700                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11701                         break;
11702                 case RENDERPATH_GL11:
11703                 case RENDERPATH_GL13:
11704                 case RENDERPATH_GLES1:
11705                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11706                         break;
11707                 }
11708         }
11709         else
11710         {
11711                 switch (vid.renderpath)
11712                 {
11713                 case RENDERPATH_GL20:
11714                 case RENDERPATH_D3D9:
11715                 case RENDERPATH_D3D10:
11716                 case RENDERPATH_D3D11:
11717                 case RENDERPATH_SOFT:
11718                 case RENDERPATH_GLES2:
11719                         RSurf_ActiveModelEntity(ent, true, true, false);
11720                         break;
11721                 case RENDERPATH_GL11:
11722                 case RENDERPATH_GL13:
11723                 case RENDERPATH_GLES1:
11724                         RSurf_ActiveModelEntity(ent, true, false, false);
11725                         break;
11726                 }
11727         }
11728
11729         surfaces = model->data_surfaces;
11730         update = model->brushq1.lightmapupdateflags;
11731
11732         // update light styles
11733         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11734         {
11735                 model_brush_lightstyleinfo_t *style;
11736                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11737                 {
11738                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11739                         {
11740                                 int *list = style->surfacelist;
11741                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11742                                 for (j = 0;j < style->numsurfaces;j++)
11743                                         update[list[j]] = true;
11744                         }
11745                 }
11746         }
11747
11748         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11749
11750         if (debug)
11751         {
11752                 R_DrawDebugModel();
11753                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11754                 return;
11755         }
11756
11757         rsurface.lightmaptexture = NULL;
11758         rsurface.deluxemaptexture = NULL;
11759         rsurface.uselightmaptexture = false;
11760         rsurface.texture = NULL;
11761         rsurface.rtlight = NULL;
11762         numsurfacelist = 0;
11763         // add visible surfaces to draw list
11764         for (i = 0;i < model->nummodelsurfaces;i++)
11765                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11766         // don't do anything if there were no surfaces
11767         if (!numsurfacelist)
11768         {
11769                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11770                 return;
11771         }
11772         // update lightmaps if needed
11773         if (update)
11774         {
11775                 int updated = 0;
11776                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11777                 {
11778                         if (update[j])
11779                         {
11780                                 updated++;
11781                                 R_BuildLightMap(ent, surfaces + j);
11782                         }
11783                 }
11784         }
11785         if (update)
11786                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11787                         if (update[j])
11788                                 R_BuildLightMap(ent, surfaces + j);
11789         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11790
11791         // add to stats if desired
11792         if (r_speeds.integer && !skysurfaces && !depthonly)
11793         {
11794                 r_refdef.stats.entities_surfaces += numsurfacelist;
11795                 for (j = 0;j < numsurfacelist;j++)
11796                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11797         }
11798
11799         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11800 }
11801
11802 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11803 {
11804         static texture_t texture;
11805         static msurface_t surface;
11806         const msurface_t *surfacelist = &surface;
11807
11808         // fake enough texture and surface state to render this geometry
11809
11810         texture.update_lastrenderframe = -1; // regenerate this texture
11811         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11812         texture.currentskinframe = skinframe;
11813         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11814         texture.offsetmapping = OFFSETMAPPING_OFF;
11815         texture.offsetscale = 1;
11816         texture.specularscalemod = 1;
11817         texture.specularpowermod = 1;
11818
11819         surface.texture = &texture;
11820         surface.num_triangles = numtriangles;
11821         surface.num_firsttriangle = firsttriangle;
11822         surface.num_vertices = numvertices;
11823         surface.num_firstvertex = firstvertex;
11824
11825         // now render it
11826         rsurface.texture = R_GetCurrentTexture(surface.texture);
11827         rsurface.lightmaptexture = NULL;
11828         rsurface.deluxemaptexture = NULL;
11829         rsurface.uselightmaptexture = false;
11830         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11831 }
11832
11833 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)
11834 {
11835         static msurface_t surface;
11836         const msurface_t *surfacelist = &surface;
11837
11838         // fake enough texture and surface state to render this geometry
11839         surface.texture = texture;
11840         surface.num_triangles = numtriangles;
11841         surface.num_firsttriangle = firsttriangle;
11842         surface.num_vertices = numvertices;
11843         surface.num_firstvertex = firstvertex;
11844
11845         // now render it
11846         rsurface.texture = R_GetCurrentTexture(surface.texture);
11847         rsurface.lightmaptexture = NULL;
11848         rsurface.deluxemaptexture = NULL;
11849         rsurface.uselightmaptexture = false;
11850         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11851 }