]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Experimental r_glsl_offsetmapping_lod cvar which applies a distance-based correction...
[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         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#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         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1930                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1931         else if (texturemode == GL_ADD)
1932                 permutation |= SHADERPERMUTATION_GLOW;
1933         else if (texturemode == GL_DECAL)
1934                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
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 * (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 * (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 * (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 * (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 * (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 * (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) * (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) * (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) * (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) && 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;
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( item->base == NULL )
3219         {
3220                 rtexture_t *dyntexture;
3221                 // check whether its a dynamic texture
3222                 // 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]
3223                 dyntexture = CL_GetDynTexture( basename );
3224                 item->base = dyntexture; // either NULL or dyntexture handle
3225         }
3226
3227         R_SkinFrame_MarkUsed(item);
3228         return item;
3229 }
3230
3231 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3232         { \
3233                 unsigned long long avgcolor[5], wsum; \
3234                 int pix, comp, w; \
3235                 avgcolor[0] = 0; \
3236                 avgcolor[1] = 0; \
3237                 avgcolor[2] = 0; \
3238                 avgcolor[3] = 0; \
3239                 avgcolor[4] = 0; \
3240                 wsum = 0; \
3241                 for(pix = 0; pix < cnt; ++pix) \
3242                 { \
3243                         w = 0; \
3244                         for(comp = 0; comp < 3; ++comp) \
3245                                 w += getpixel; \
3246                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3247                         { \
3248                                 ++wsum; \
3249                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3250                                 w = getpixel; \
3251                                 for(comp = 0; comp < 3; ++comp) \
3252                                         avgcolor[comp] += getpixel * w; \
3253                                 avgcolor[3] += w; \
3254                         } \
3255                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                         avgcolor[4] += getpixel; \
3257                 } \
3258                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3259                         avgcolor[3] = 1; \
3260                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3261                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3262                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3264         }
3265
3266 extern cvar_t gl_picmip;
3267 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3268 {
3269         int j;
3270         unsigned char *pixels;
3271         unsigned char *bumppixels;
3272         unsigned char *basepixels = NULL;
3273         int basepixels_width = 0;
3274         int basepixels_height = 0;
3275         skinframe_t *skinframe;
3276         rtexture_t *ddsbase = NULL;
3277         qboolean ddshasalpha = false;
3278         float ddsavgcolor[4];
3279         char basename[MAX_QPATH];
3280         int miplevel = R_PicmipForFlags(textureflags);
3281         int savemiplevel = miplevel;
3282         int mymiplevel;
3283
3284         if (cls.state == ca_dedicated)
3285                 return NULL;
3286
3287         // return an existing skinframe if already loaded
3288         // if loading of the first image fails, don't make a new skinframe as it
3289         // would cause all future lookups of this to be missing
3290         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3291         if (skinframe && skinframe->base)
3292                 return skinframe;
3293
3294         Image_StripImageExtension(name, basename, sizeof(basename));
3295
3296         // check for DDS texture file first
3297         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3298         {
3299                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3300                 if (basepixels == NULL)
3301                         return NULL;
3302         }
3303
3304         // FIXME handle miplevel
3305
3306         if (developer_loading.integer)
3307                 Con_Printf("loading skin \"%s\"\n", name);
3308
3309         // we've got some pixels to store, so really allocate this new texture now
3310         if (!skinframe)
3311                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3312         skinframe->stain = NULL;
3313         skinframe->merged = NULL;
3314         skinframe->base = NULL;
3315         skinframe->pants = NULL;
3316         skinframe->shirt = NULL;
3317         skinframe->nmap = NULL;
3318         skinframe->gloss = NULL;
3319         skinframe->glow = NULL;
3320         skinframe->fog = NULL;
3321         skinframe->reflect = NULL;
3322         skinframe->hasalpha = false;
3323
3324         if (ddsbase)
3325         {
3326                 skinframe->base = ddsbase;
3327                 skinframe->hasalpha = ddshasalpha;
3328                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3329                 if (r_loadfog && skinframe->hasalpha)
3330                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3331                 //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]);
3332         }
3333         else
3334         {
3335                 basepixels_width = image_width;
3336                 basepixels_height = image_height;
3337                 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);
3338                 if (textureflags & TEXF_ALPHA)
3339                 {
3340                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3341                         {
3342                                 if (basepixels[j] < 255)
3343                                 {
3344                                         skinframe->hasalpha = true;
3345                                         break;
3346                                 }
3347                         }
3348                         if (r_loadfog && skinframe->hasalpha)
3349                         {
3350                                 // has transparent pixels
3351                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3352                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3353                                 {
3354                                         pixels[j+0] = 255;
3355                                         pixels[j+1] = 255;
3356                                         pixels[j+2] = 255;
3357                                         pixels[j+3] = basepixels[j+3];
3358                                 }
3359                                 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);
3360                                 Mem_Free(pixels);
3361                         }
3362                 }
3363                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3364 #ifndef USE_GLES2
3365                 //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]);
3366                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3367                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3368                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3369                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3370 #endif
3371         }
3372
3373         if (r_loaddds)
3374         {
3375                 mymiplevel = savemiplevel;
3376                 if (r_loadnormalmap)
3377                         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);
3378                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3379                 if (r_loadgloss)
3380                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3381                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3383                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384         }
3385
3386         // _norm is the name used by tenebrae and has been adopted as standard
3387         if (r_loadnormalmap && skinframe->nmap == NULL)
3388         {
3389                 mymiplevel = savemiplevel;
3390                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3391                 {
3392                         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);
3393                         Mem_Free(pixels);
3394                         pixels = NULL;
3395                 }
3396                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3397                 {
3398                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3399                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3400                         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);
3401                         Mem_Free(pixels);
3402                         Mem_Free(bumppixels);
3403                 }
3404                 else if (r_shadow_bumpscale_basetexture.value > 0)
3405                 {
3406                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3407                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3408                         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);
3409                         Mem_Free(pixels);
3410                 }
3411 #ifndef USE_GLES2
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3413                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         // _luma is supported only for tenebrae compatibility
3418         // _glow is the preferred name
3419         mymiplevel = savemiplevel;
3420         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))))
3421         {
3422                 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);
3423 #ifndef USE_GLES2
3424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3425                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3426 #endif
3427                 Mem_Free(pixels);pixels = NULL;
3428         }
3429
3430         mymiplevel = savemiplevel;
3431         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3432         {
3433                 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);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3436                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438                 Mem_Free(pixels);
3439                 pixels = NULL;
3440         }
3441
3442         mymiplevel = savemiplevel;
3443         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3444         {
3445                 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);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3448                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3449 #endif
3450                 Mem_Free(pixels);
3451                 pixels = NULL;
3452         }
3453
3454         mymiplevel = savemiplevel;
3455         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3456         {
3457                 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);
3458 #ifndef USE_GLES2
3459                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3460                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3461 #endif
3462                 Mem_Free(pixels);
3463                 pixels = NULL;
3464         }
3465
3466         mymiplevel = savemiplevel;
3467         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3468         {
3469                 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);
3470 #ifndef USE_GLES2
3471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3472                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3473 #endif
3474                 Mem_Free(pixels);
3475                 pixels = NULL;
3476         }
3477
3478         if (basepixels)
3479                 Mem_Free(basepixels);
3480
3481         return skinframe;
3482 }
3483
3484 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3485 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3486 {
3487         int i;
3488         unsigned char *temp1, *temp2;
3489         skinframe_t *skinframe;
3490
3491         if (cls.state == ca_dedicated)
3492                 return NULL;
3493
3494         // if already loaded just return it, otherwise make a new skinframe
3495         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3496         if (skinframe && skinframe->base)
3497                 return skinframe;
3498
3499         skinframe->stain = NULL;
3500         skinframe->merged = NULL;
3501         skinframe->base = NULL;
3502         skinframe->pants = NULL;
3503         skinframe->shirt = NULL;
3504         skinframe->nmap = NULL;
3505         skinframe->gloss = NULL;
3506         skinframe->glow = NULL;
3507         skinframe->fog = NULL;
3508         skinframe->reflect = NULL;
3509         skinframe->hasalpha = false;
3510
3511         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3512         if (!skindata)
3513                 return NULL;
3514
3515         if (developer_loading.integer)
3516                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3517
3518         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3519         {
3520                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3521                 temp2 = temp1 + width * height * 4;
3522                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3523                 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);
3524                 Mem_Free(temp1);
3525         }
3526         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3527         if (textureflags & TEXF_ALPHA)
3528         {
3529                 for (i = 3;i < width * height * 4;i += 4)
3530                 {
3531                         if (skindata[i] < 255)
3532                         {
3533                                 skinframe->hasalpha = true;
3534                                 break;
3535                         }
3536                 }
3537                 if (r_loadfog && skinframe->hasalpha)
3538                 {
3539                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3540                         memcpy(fogpixels, skindata, width * height * 4);
3541                         for (i = 0;i < width * height * 4;i += 4)
3542                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3543                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3544                         Mem_Free(fogpixels);
3545                 }
3546         }
3547
3548         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3549         //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]);
3550
3551         return skinframe;
3552 }
3553
3554 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3555 {
3556         int i;
3557         int featuresmask;
3558         skinframe_t *skinframe;
3559
3560         if (cls.state == ca_dedicated)
3561                 return NULL;
3562
3563         // if already loaded just return it, otherwise make a new skinframe
3564         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3565         if (skinframe && skinframe->base)
3566                 return skinframe;
3567
3568         skinframe->stain = NULL;
3569         skinframe->merged = NULL;
3570         skinframe->base = NULL;
3571         skinframe->pants = NULL;
3572         skinframe->shirt = NULL;
3573         skinframe->nmap = NULL;
3574         skinframe->gloss = NULL;
3575         skinframe->glow = NULL;
3576         skinframe->fog = NULL;
3577         skinframe->reflect = NULL;
3578         skinframe->hasalpha = false;
3579
3580         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3581         if (!skindata)
3582                 return NULL;
3583
3584         if (developer_loading.integer)
3585                 Con_Printf("loading quake skin \"%s\"\n", name);
3586
3587         // 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)
3588         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3589         memcpy(skinframe->qpixels, skindata, width*height);
3590         skinframe->qwidth = width;
3591         skinframe->qheight = height;
3592
3593         featuresmask = 0;
3594         for (i = 0;i < width * height;i++)
3595                 featuresmask |= palette_featureflags[skindata[i]];
3596
3597         skinframe->hasalpha = false;
3598         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3599         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3600         skinframe->qgeneratemerged = true;
3601         skinframe->qgeneratebase = skinframe->qhascolormapping;
3602         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3603
3604         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3605         //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]);
3606
3607         return skinframe;
3608 }
3609
3610 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3611 {
3612         int width;
3613         int height;
3614         unsigned char *skindata;
3615
3616         if (!skinframe->qpixels)
3617                 return;
3618
3619         if (!skinframe->qhascolormapping)
3620                 colormapped = false;
3621
3622         if (colormapped)
3623         {
3624                 if (!skinframe->qgeneratebase)
3625                         return;
3626         }
3627         else
3628         {
3629                 if (!skinframe->qgeneratemerged)
3630                         return;
3631         }
3632
3633         width = skinframe->qwidth;
3634         height = skinframe->qheight;
3635         skindata = skinframe->qpixels;
3636
3637         if (skinframe->qgeneratenmap)
3638         {
3639                 unsigned char *temp1, *temp2;
3640                 skinframe->qgeneratenmap = false;
3641                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3642                 temp2 = temp1 + width * height * 4;
3643                 // use either a custom palette or the quake palette
3644                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3645                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3646                 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);
3647                 Mem_Free(temp1);
3648         }
3649
3650         if (skinframe->qgenerateglow)
3651         {
3652                 skinframe->qgenerateglow = false;
3653                 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
3654         }
3655
3656         if (colormapped)
3657         {
3658                 skinframe->qgeneratebase = false;
3659                 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);
3660                 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);
3661                 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);
3662         }
3663         else
3664         {
3665                 skinframe->qgeneratemerged = false;
3666                 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);
3667         }
3668
3669         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3670         {
3671                 Mem_Free(skinframe->qpixels);
3672                 skinframe->qpixels = NULL;
3673         }
3674 }
3675
3676 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)
3677 {
3678         int i;
3679         skinframe_t *skinframe;
3680
3681         if (cls.state == ca_dedicated)
3682                 return NULL;
3683
3684         // if already loaded just return it, otherwise make a new skinframe
3685         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3686         if (skinframe && skinframe->base)
3687                 return skinframe;
3688
3689         skinframe->stain = NULL;
3690         skinframe->merged = NULL;
3691         skinframe->base = NULL;
3692         skinframe->pants = NULL;
3693         skinframe->shirt = NULL;
3694         skinframe->nmap = NULL;
3695         skinframe->gloss = NULL;
3696         skinframe->glow = NULL;
3697         skinframe->fog = NULL;
3698         skinframe->reflect = NULL;
3699         skinframe->hasalpha = false;
3700
3701         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3702         if (!skindata)
3703                 return NULL;
3704
3705         if (developer_loading.integer)
3706                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3707
3708         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3709         if (textureflags & TEXF_ALPHA)
3710         {
3711                 for (i = 0;i < width * height;i++)
3712                 {
3713                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3714                         {
3715                                 skinframe->hasalpha = true;
3716                                 break;
3717                         }
3718                 }
3719                 if (r_loadfog && skinframe->hasalpha)
3720                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3721         }
3722
3723         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3724         //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]);
3725
3726         return skinframe;
3727 }
3728
3729 skinframe_t *R_SkinFrame_LoadMissing(void)
3730 {
3731         skinframe_t *skinframe;
3732
3733         if (cls.state == ca_dedicated)
3734                 return NULL;
3735
3736         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3737         skinframe->stain = NULL;
3738         skinframe->merged = NULL;
3739         skinframe->base = NULL;
3740         skinframe->pants = NULL;
3741         skinframe->shirt = NULL;
3742         skinframe->nmap = NULL;
3743         skinframe->gloss = NULL;
3744         skinframe->glow = NULL;
3745         skinframe->fog = NULL;
3746         skinframe->reflect = NULL;
3747         skinframe->hasalpha = false;
3748
3749         skinframe->avgcolor[0] = rand() / RAND_MAX;
3750         skinframe->avgcolor[1] = rand() / RAND_MAX;
3751         skinframe->avgcolor[2] = rand() / RAND_MAX;
3752         skinframe->avgcolor[3] = 1;
3753
3754         return skinframe;
3755 }
3756
3757 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3758 typedef struct suffixinfo_s
3759 {
3760         const char *suffix;
3761         qboolean flipx, flipy, flipdiagonal;
3762 }
3763 suffixinfo_t;
3764 static suffixinfo_t suffix[3][6] =
3765 {
3766         {
3767                 {"px",   false, false, false},
3768                 {"nx",   false, false, false},
3769                 {"py",   false, false, false},
3770                 {"ny",   false, false, false},
3771                 {"pz",   false, false, false},
3772                 {"nz",   false, false, false}
3773         },
3774         {
3775                 {"posx", false, false, false},
3776                 {"negx", false, false, false},
3777                 {"posy", false, false, false},
3778                 {"negy", false, false, false},
3779                 {"posz", false, false, false},
3780                 {"negz", false, false, false}
3781         },
3782         {
3783                 {"rt",    true, false,  true},
3784                 {"lf",   false,  true,  true},
3785                 {"ft",    true,  true, false},
3786                 {"bk",   false, false, false},
3787                 {"up",    true, false,  true},
3788                 {"dn",    true, false,  true}
3789         }
3790 };
3791
3792 static int componentorder[4] = {0, 1, 2, 3};
3793
3794 rtexture_t *R_LoadCubemap(const char *basename)
3795 {
3796         int i, j, cubemapsize;
3797         unsigned char *cubemappixels, *image_buffer;
3798         rtexture_t *cubemaptexture;
3799         char name[256];
3800         // must start 0 so the first loadimagepixels has no requested width/height
3801         cubemapsize = 0;
3802         cubemappixels = NULL;
3803         cubemaptexture = NULL;
3804         // keep trying different suffix groups (posx, px, rt) until one loads
3805         for (j = 0;j < 3 && !cubemappixels;j++)
3806         {
3807                 // load the 6 images in the suffix group
3808                 for (i = 0;i < 6;i++)
3809                 {
3810                         // generate an image name based on the base and and suffix
3811                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3812                         // load it
3813                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3814                         {
3815                                 // an image loaded, make sure width and height are equal
3816                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3817                                 {
3818                                         // if this is the first image to load successfully, allocate the cubemap memory
3819                                         if (!cubemappixels && image_width >= 1)
3820                                         {
3821                                                 cubemapsize = image_width;
3822                                                 // note this clears to black, so unavailable sides are black
3823                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3824                                         }
3825                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3826                                         if (cubemappixels)
3827                                                 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);
3828                                 }
3829                                 else
3830                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3831                                 // free the image
3832                                 Mem_Free(image_buffer);
3833                         }
3834                 }
3835         }
3836         // if a cubemap loaded, upload it
3837         if (cubemappixels)
3838         {
3839                 if (developer_loading.integer)
3840                         Con_Printf("loading cubemap \"%s\"\n", basename);
3841
3842                 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);
3843                 Mem_Free(cubemappixels);
3844         }
3845         else
3846         {
3847                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3848                 if (developer_loading.integer)
3849                 {
3850                         Con_Printf("(tried tried images ");
3851                         for (j = 0;j < 3;j++)
3852                                 for (i = 0;i < 6;i++)
3853                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3854                         Con_Print(" and was unable to find any of them).\n");
3855                 }
3856         }
3857         return cubemaptexture;
3858 }
3859
3860 rtexture_t *R_GetCubemap(const char *basename)
3861 {
3862         int i;
3863         for (i = 0;i < r_texture_numcubemaps;i++)
3864                 if (r_texture_cubemaps[i] != NULL)
3865                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3866                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3867         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3868                 return r_texture_whitecube;
3869         r_texture_numcubemaps++;
3870         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3871         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3872         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3873         return r_texture_cubemaps[i]->texture;
3874 }
3875
3876 void R_FreeCubemap(const char *basename)
3877 {
3878         int i;
3879
3880         for (i = 0;i < r_texture_numcubemaps;i++)
3881         {
3882                 if (r_texture_cubemaps[i] != NULL)
3883                 {
3884                         if (r_texture_cubemaps[i]->texture)
3885                         {
3886                                 if (developer_loading.integer)
3887                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3888                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3889                                 Mem_Free(r_texture_cubemaps[i]);
3890                                 r_texture_cubemaps[i] = NULL;
3891                         }
3892                 }
3893         }
3894 }
3895
3896 void R_FreeCubemaps(void)
3897 {
3898         int i;
3899         for (i = 0;i < r_texture_numcubemaps;i++)
3900         {
3901                 if (developer_loading.integer)
3902                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3903                 if (r_texture_cubemaps[i] != NULL)
3904                 {
3905                         if (r_texture_cubemaps[i]->texture)
3906                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3907                         Mem_Free(r_texture_cubemaps[i]);
3908                 }
3909         }
3910         r_texture_numcubemaps = 0;
3911 }
3912
3913 void R_Main_FreeViewCache(void)
3914 {
3915         if (r_refdef.viewcache.entityvisible)
3916                 Mem_Free(r_refdef.viewcache.entityvisible);
3917         if (r_refdef.viewcache.world_pvsbits)
3918                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3919         if (r_refdef.viewcache.world_leafvisible)
3920                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3921         if (r_refdef.viewcache.world_surfacevisible)
3922                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3923         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3924 }
3925
3926 void R_Main_ResizeViewCache(void)
3927 {
3928         int numentities = r_refdef.scene.numentities;
3929         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3930         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3931         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3932         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3933         if (r_refdef.viewcache.maxentities < numentities)
3934         {
3935                 r_refdef.viewcache.maxentities = numentities;
3936                 if (r_refdef.viewcache.entityvisible)
3937                         Mem_Free(r_refdef.viewcache.entityvisible);
3938                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3939         }
3940         if (r_refdef.viewcache.world_numclusters != numclusters)
3941         {
3942                 r_refdef.viewcache.world_numclusters = numclusters;
3943                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3944                 if (r_refdef.viewcache.world_pvsbits)
3945                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3946                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3947         }
3948         if (r_refdef.viewcache.world_numleafs != numleafs)
3949         {
3950                 r_refdef.viewcache.world_numleafs = numleafs;
3951                 if (r_refdef.viewcache.world_leafvisible)
3952                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3953                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3954         }
3955         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3956         {
3957                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3958                 if (r_refdef.viewcache.world_surfacevisible)
3959                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3960                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3961         }
3962 }
3963
3964 extern rtexture_t *loadingscreentexture;
3965 void gl_main_start(void)
3966 {
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978
3979         r_loaddds = r_texture_dds_load.integer != 0;
3980         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3981
3982         switch(vid.renderpath)
3983         {
3984         case RENDERPATH_GL20:
3985         case RENDERPATH_D3D9:
3986         case RENDERPATH_D3D10:
3987         case RENDERPATH_D3D11:
3988         case RENDERPATH_SOFT:
3989         case RENDERPATH_GLES2:
3990                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991                 Cvar_SetValueQuick(&gl_combine, 1);
3992                 Cvar_SetValueQuick(&r_glsl, 1);
3993                 r_loadnormalmap = true;
3994                 r_loadgloss = true;
3995                 r_loadfog = false;
3996                 break;
3997         case RENDERPATH_GL13:
3998         case RENDERPATH_GLES1:
3999                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000                 Cvar_SetValueQuick(&gl_combine, 1);
4001                 Cvar_SetValueQuick(&r_glsl, 0);
4002                 r_loadnormalmap = false;
4003                 r_loadgloss = false;
4004                 r_loadfog = true;
4005                 break;
4006         case RENDERPATH_GL11:
4007                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4008                 Cvar_SetValueQuick(&gl_combine, 0);
4009                 Cvar_SetValueQuick(&r_glsl, 0);
4010                 r_loadnormalmap = false;
4011                 r_loadgloss = false;
4012                 r_loadfog = true;
4013                 break;
4014         }
4015
4016         R_AnimCache_Free();
4017         R_FrameData_Reset();
4018
4019         r_numqueries = 0;
4020         r_maxqueries = 0;
4021         memset(r_queries, 0, sizeof(r_queries));
4022
4023         r_qwskincache = NULL;
4024         r_qwskincache_size = 0;
4025
4026         // due to caching of texture_t references, the collision cache must be reset
4027         Collision_Cache_Reset(true);
4028
4029         // set up r_skinframe loading system for textures
4030         memset(&r_skinframe, 0, sizeof(r_skinframe));
4031         r_skinframe.loadsequence = 1;
4032         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4033
4034         r_main_texturepool = R_AllocTexturePool();
4035         R_BuildBlankTextures();
4036         R_BuildNoTexture();
4037         if (vid.support.arb_texture_cube_map)
4038         {
4039                 R_BuildWhiteCube();
4040                 R_BuildNormalizationCube();
4041         }
4042         r_texture_fogattenuation = NULL;
4043         r_texture_fogheighttexture = NULL;
4044         r_texture_gammaramps = NULL;
4045         //r_texture_fogintensity = NULL;
4046         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4047         memset(&r_waterstate, 0, sizeof(r_waterstate));
4048         r_glsl_permutation = NULL;
4049         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4050         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4051         glslshaderstring = NULL;
4052 #ifdef SUPPORTD3D
4053         r_hlsl_permutation = NULL;
4054         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4055         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4056 #endif
4057         hlslshaderstring = NULL;
4058         memset(&r_svbsp, 0, sizeof (r_svbsp));
4059
4060         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4061         r_texture_numcubemaps = 0;
4062
4063         r_refdef.fogmasktable_density = 0;
4064 }
4065
4066 void gl_main_shutdown(void)
4067 {
4068         R_AnimCache_Free();
4069         R_FrameData_Reset();
4070
4071         R_Main_FreeViewCache();
4072
4073         switch(vid.renderpath)
4074         {
4075         case RENDERPATH_GL11:
4076         case RENDERPATH_GL13:
4077         case RENDERPATH_GL20:
4078         case RENDERPATH_GLES1:
4079         case RENDERPATH_GLES2:
4080 #ifdef GL_SAMPLES_PASSED_ARB
4081                 if (r_maxqueries)
4082                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4083 #endif
4084                 break;
4085         case RENDERPATH_D3D9:
4086                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087                 break;
4088         case RENDERPATH_D3D10:
4089                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090                 break;
4091         case RENDERPATH_D3D11:
4092                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4093                 break;
4094         case RENDERPATH_SOFT:
4095                 break;
4096         }
4097
4098         r_numqueries = 0;
4099         r_maxqueries = 0;
4100         memset(r_queries, 0, sizeof(r_queries));
4101
4102         r_qwskincache = NULL;
4103         r_qwskincache_size = 0;
4104
4105         // clear out the r_skinframe state
4106         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4107         memset(&r_skinframe, 0, sizeof(r_skinframe));
4108
4109         if (r_svbsp.nodes)
4110                 Mem_Free(r_svbsp.nodes);
4111         memset(&r_svbsp, 0, sizeof (r_svbsp));
4112         R_FreeTexturePool(&r_main_texturepool);
4113         loadingscreentexture = NULL;
4114         r_texture_blanknormalmap = NULL;
4115         r_texture_white = NULL;
4116         r_texture_grey128 = NULL;
4117         r_texture_black = NULL;
4118         r_texture_whitecube = NULL;
4119         r_texture_normalizationcube = NULL;
4120         r_texture_fogattenuation = NULL;
4121         r_texture_fogheighttexture = NULL;
4122         r_texture_gammaramps = NULL;
4123         r_texture_numcubemaps = 0;
4124         //r_texture_fogintensity = NULL;
4125         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4126         memset(&r_waterstate, 0, sizeof(r_waterstate));
4127         R_GLSL_Restart_f();
4128
4129         r_glsl_permutation = NULL;
4130         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4131         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4132         glslshaderstring = NULL;
4133 #ifdef SUPPORTD3D
4134         r_hlsl_permutation = NULL;
4135         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4136         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4137 #endif
4138         hlslshaderstring = NULL;
4139 }
4140
4141 extern void CL_ParseEntityLump(char *entitystring);
4142 void gl_main_newmap(void)
4143 {
4144         // FIXME: move this code to client
4145         char *entities, entname[MAX_QPATH];
4146         if (r_qwskincache)
4147                 Mem_Free(r_qwskincache);
4148         r_qwskincache = NULL;
4149         r_qwskincache_size = 0;
4150         if (cl.worldmodel)
4151         {
4152                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4153                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4154                 {
4155                         CL_ParseEntityLump(entities);
4156                         Mem_Free(entities);
4157                         return;
4158                 }
4159                 if (cl.worldmodel->brush.entities)
4160                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4161         }
4162         R_Main_FreeViewCache();
4163
4164         R_FrameData_Reset();
4165 }
4166
4167 void GL_Main_Init(void)
4168 {
4169         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4170
4171         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4172         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4173         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4174         if (gamemode == GAME_NEHAHRA)
4175         {
4176                 Cvar_RegisterVariable (&gl_fogenable);
4177                 Cvar_RegisterVariable (&gl_fogdensity);
4178                 Cvar_RegisterVariable (&gl_fogred);
4179                 Cvar_RegisterVariable (&gl_foggreen);
4180                 Cvar_RegisterVariable (&gl_fogblue);
4181                 Cvar_RegisterVariable (&gl_fogstart);
4182                 Cvar_RegisterVariable (&gl_fogend);
4183                 Cvar_RegisterVariable (&gl_skyclip);
4184         }
4185         Cvar_RegisterVariable(&r_motionblur);
4186         Cvar_RegisterVariable(&r_damageblur);
4187         Cvar_RegisterVariable(&r_motionblur_averaging);
4188         Cvar_RegisterVariable(&r_motionblur_randomize);
4189         Cvar_RegisterVariable(&r_motionblur_minblur);
4190         Cvar_RegisterVariable(&r_motionblur_maxblur);
4191         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4192         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4193         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4194         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4195         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4196         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4197         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4198         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4199         Cvar_RegisterVariable(&r_equalize_entities_by);
4200         Cvar_RegisterVariable(&r_equalize_entities_to);
4201         Cvar_RegisterVariable(&r_depthfirst);
4202         Cvar_RegisterVariable(&r_useinfinitefarclip);
4203         Cvar_RegisterVariable(&r_farclip_base);
4204         Cvar_RegisterVariable(&r_farclip_world);
4205         Cvar_RegisterVariable(&r_nearclip);
4206         Cvar_RegisterVariable(&r_deformvertexes);
4207         Cvar_RegisterVariable(&r_transparent);
4208         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4209         Cvar_RegisterVariable(&r_showoverdraw);
4210         Cvar_RegisterVariable(&r_showbboxes);
4211         Cvar_RegisterVariable(&r_showsurfaces);
4212         Cvar_RegisterVariable(&r_showtris);
4213         Cvar_RegisterVariable(&r_shownormals);
4214         Cvar_RegisterVariable(&r_showlighting);
4215         Cvar_RegisterVariable(&r_showshadowvolumes);
4216         Cvar_RegisterVariable(&r_showcollisionbrushes);
4217         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4218         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4219         Cvar_RegisterVariable(&r_showdisabledepthtest);
4220         Cvar_RegisterVariable(&r_drawportals);
4221         Cvar_RegisterVariable(&r_drawentities);
4222         Cvar_RegisterVariable(&r_draw2d);
4223         Cvar_RegisterVariable(&r_drawworld);
4224         Cvar_RegisterVariable(&r_cullentities_trace);
4225         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4226         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4227         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4228         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4229         Cvar_RegisterVariable(&r_sortentities);
4230         Cvar_RegisterVariable(&r_drawviewmodel);
4231         Cvar_RegisterVariable(&r_drawexteriormodel);
4232         Cvar_RegisterVariable(&r_speeds);
4233         Cvar_RegisterVariable(&r_fullbrights);
4234         Cvar_RegisterVariable(&r_wateralpha);
4235         Cvar_RegisterVariable(&r_dynamic);
4236         Cvar_RegisterVariable(&r_fakelight);
4237         Cvar_RegisterVariable(&r_fakelight_intensity);
4238         Cvar_RegisterVariable(&r_fullbright);
4239         Cvar_RegisterVariable(&r_shadows);
4240         Cvar_RegisterVariable(&r_shadows_darken);
4241         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4242         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4243         Cvar_RegisterVariable(&r_shadows_throwdistance);
4244         Cvar_RegisterVariable(&r_shadows_throwdirection);
4245         Cvar_RegisterVariable(&r_shadows_focus);
4246         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4247         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4248         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4249         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4250         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4251         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4252         Cvar_RegisterVariable(&r_fog_exp2);
4253         Cvar_RegisterVariable(&r_fog_clear);
4254         Cvar_RegisterVariable(&r_drawfog);
4255         Cvar_RegisterVariable(&r_transparentdepthmasking);
4256         Cvar_RegisterVariable(&r_transparent_sortmindist);
4257         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4258         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4259         Cvar_RegisterVariable(&r_texture_dds_load);
4260         Cvar_RegisterVariable(&r_texture_dds_save);
4261         Cvar_RegisterVariable(&r_textureunits);
4262         Cvar_RegisterVariable(&gl_combine);
4263         Cvar_RegisterVariable(&r_viewfbo);
4264         Cvar_RegisterVariable(&r_viewscale);
4265         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4266         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4267         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4271         Cvar_RegisterVariable(&r_glsl);
4272         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4273         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4274         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4275         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4281         Cvar_RegisterVariable(&r_glsl_postprocess);
4282         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4283         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4284         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4290
4291         Cvar_RegisterVariable(&r_water);
4292         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4293         Cvar_RegisterVariable(&r_water_clippingplanebias);
4294         Cvar_RegisterVariable(&r_water_refractdistort);
4295         Cvar_RegisterVariable(&r_water_reflectdistort);
4296         Cvar_RegisterVariable(&r_water_scissormode);
4297         Cvar_RegisterVariable(&r_water_lowquality);
4298
4299         Cvar_RegisterVariable(&r_lerpsprites);
4300         Cvar_RegisterVariable(&r_lerpmodels);
4301         Cvar_RegisterVariable(&r_lerplightstyles);
4302         Cvar_RegisterVariable(&r_waterscroll);
4303         Cvar_RegisterVariable(&r_bloom);
4304         Cvar_RegisterVariable(&r_bloom_colorscale);
4305         Cvar_RegisterVariable(&r_bloom_brighten);
4306         Cvar_RegisterVariable(&r_bloom_blur);
4307         Cvar_RegisterVariable(&r_bloom_resolution);
4308         Cvar_RegisterVariable(&r_bloom_colorexponent);
4309         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4310         Cvar_RegisterVariable(&r_hdr);
4311         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4312         Cvar_RegisterVariable(&r_hdr_glowintensity);
4313         Cvar_RegisterVariable(&r_hdr_range);
4314         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4315         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4316         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4317         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4321         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4322         Cvar_RegisterVariable(&developer_texturelogging);
4323         Cvar_RegisterVariable(&gl_lightmaps);
4324         Cvar_RegisterVariable(&r_test);
4325         Cvar_RegisterVariable(&r_glsl_saturation);
4326         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4327         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4328         Cvar_RegisterVariable(&r_framedatasize);
4329         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4330                 Cvar_SetValue("r_fullbrights", 0);
4331         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4332 }
4333
4334 extern void R_Textures_Init(void);
4335 extern void GL_Draw_Init(void);
4336 extern void GL_Main_Init(void);
4337 extern void R_Shadow_Init(void);
4338 extern void R_Sky_Init(void);
4339 extern void GL_Surf_Init(void);
4340 extern void R_Particles_Init(void);
4341 extern void R_Explosion_Init(void);
4342 extern void gl_backend_init(void);
4343 extern void Sbar_Init(void);
4344 extern void R_LightningBeams_Init(void);
4345 extern void Mod_RenderInit(void);
4346 extern void Font_Init(void);
4347
4348 void Render_Init(void)
4349 {
4350         gl_backend_init();
4351         R_Textures_Init();
4352         GL_Main_Init();
4353         Font_Init();
4354         GL_Draw_Init();
4355         R_Shadow_Init();
4356         R_Sky_Init();
4357         GL_Surf_Init();
4358         Sbar_Init();
4359         R_Particles_Init();
4360         R_Explosion_Init();
4361         R_LightningBeams_Init();
4362         Mod_RenderInit();
4363 }
4364
4365 /*
4366 ===============
4367 GL_Init
4368 ===============
4369 */
4370 #ifndef USE_GLES2
4371 extern char *ENGINE_EXTENSIONS;
4372 void GL_Init (void)
4373 {
4374         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4375         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4376         gl_version = (const char *)qglGetString(GL_VERSION);
4377         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4378
4379         if (!gl_extensions)
4380                 gl_extensions = "";
4381         if (!gl_platformextensions)
4382                 gl_platformextensions = "";
4383
4384         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4385         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4386         Con_Printf("GL_VERSION: %s\n", gl_version);
4387         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4388         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4389
4390         VID_CheckExtensions();
4391
4392         // LordHavoc: report supported extensions
4393         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4394
4395         // clear to black (loading plaque will be seen over this)
4396         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4397 }
4398 #endif
4399
4400 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4401 {
4402         int i;
4403         mplane_t *p;
4404         if (r_trippy.integer)
4405                 return false;
4406         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4407         {
4408                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4409                 if (i == 4)
4410                         continue;
4411                 p = r_refdef.view.frustum + i;
4412                 switch(p->signbits)
4413                 {
4414                 default:
4415                 case 0:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 1:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 2:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 3:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 4:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 5:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 6:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 7:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 }
4448         }
4449         return false;
4450 }
4451
4452 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4453 {
4454         int i;
4455         const mplane_t *p;
4456         if (r_trippy.integer)
4457                 return false;
4458         for (i = 0;i < numplanes;i++)
4459         {
4460                 p = planes + i;
4461                 switch(p->signbits)
4462                 {
4463                 default:
4464                 case 0:
4465                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 1:
4469                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 2:
4473                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 3:
4477                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 4:
4481                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 case 5:
4485                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4486                                 return true;
4487                         break;
4488                 case 6:
4489                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4490                                 return true;
4491                         break;
4492                 case 7:
4493                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 }
4497         }
4498         return false;
4499 }
4500
4501 //==================================================================================
4502
4503 // LordHavoc: this stores temporary data used within the same frame
4504
4505 typedef struct r_framedata_mem_s
4506 {
4507         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4508         size_t size; // how much usable space
4509         size_t current; // how much space in use
4510         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4511         size_t wantedsize; // how much space was allocated
4512         unsigned char *data; // start of real data (16byte aligned)
4513 }
4514 r_framedata_mem_t;
4515
4516 static r_framedata_mem_t *r_framedata_mem;
4517
4518 void R_FrameData_Reset(void)
4519 {
4520         while (r_framedata_mem)
4521         {
4522                 r_framedata_mem_t *next = r_framedata_mem->purge;
4523                 Mem_Free(r_framedata_mem);
4524                 r_framedata_mem = next;
4525         }
4526 }
4527
4528 void R_FrameData_Resize(void)
4529 {
4530         size_t wantedsize;
4531         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4532         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4533         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4534         {
4535                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4536                 newmem->wantedsize = wantedsize;
4537                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4538                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4539                 newmem->current = 0;
4540                 newmem->mark = 0;
4541                 newmem->purge = r_framedata_mem;
4542                 r_framedata_mem = newmem;
4543         }
4544 }
4545
4546 void R_FrameData_NewFrame(void)
4547 {
4548         R_FrameData_Resize();
4549         if (!r_framedata_mem)
4550                 return;
4551         // if we ran out of space on the last frame, free the old memory now
4552         while (r_framedata_mem->purge)
4553         {
4554                 // repeatedly remove the second item in the list, leaving only head
4555                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4556                 Mem_Free(r_framedata_mem->purge);
4557                 r_framedata_mem->purge = next;
4558         }
4559         // reset the current mem pointer
4560         r_framedata_mem->current = 0;
4561         r_framedata_mem->mark = 0;
4562 }
4563
4564 void *R_FrameData_Alloc(size_t size)
4565 {
4566         void *data;
4567
4568         // align to 16 byte boundary - the data pointer is already aligned, so we
4569         // only need to ensure the size of every allocation is also aligned
4570         size = (size + 15) & ~15;
4571
4572         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4573         {
4574                 // emergency - we ran out of space, allocate more memory
4575                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4576                 R_FrameData_Resize();
4577         }
4578
4579         data = r_framedata_mem->data + r_framedata_mem->current;
4580         r_framedata_mem->current += size;
4581
4582         // count the usage for stats
4583         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4584         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4585
4586         return (void *)data;
4587 }
4588
4589 void *R_FrameData_Store(size_t size, void *data)
4590 {
4591         void *d = R_FrameData_Alloc(size);
4592         if (d && data)
4593                 memcpy(d, data, size);
4594         return d;
4595 }
4596
4597 void R_FrameData_SetMark(void)
4598 {
4599         if (!r_framedata_mem)
4600                 return;
4601         r_framedata_mem->mark = r_framedata_mem->current;
4602 }
4603
4604 void R_FrameData_ReturnToMark(void)
4605 {
4606         if (!r_framedata_mem)
4607                 return;
4608         r_framedata_mem->current = r_framedata_mem->mark;
4609 }
4610
4611 //==================================================================================
4612
4613 // LordHavoc: animcache originally written by Echon, rewritten since then
4614
4615 /**
4616  * Animation cache prevents re-generating mesh data for an animated model
4617  * multiple times in one frame for lighting, shadowing, reflections, etc.
4618  */
4619
4620 void R_AnimCache_Free(void)
4621 {
4622 }
4623
4624 void R_AnimCache_ClearCache(void)
4625 {
4626         int i;
4627         entity_render_t *ent;
4628
4629         for (i = 0;i < r_refdef.scene.numentities;i++)
4630         {
4631                 ent = r_refdef.scene.entities[i];
4632                 ent->animcache_vertex3f = NULL;
4633                 ent->animcache_normal3f = NULL;
4634                 ent->animcache_svector3f = NULL;
4635                 ent->animcache_tvector3f = NULL;
4636                 ent->animcache_vertexmesh = NULL;
4637                 ent->animcache_vertex3fbuffer = NULL;
4638                 ent->animcache_vertexmeshbuffer = NULL;
4639         }
4640 }
4641
4642 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4643 {
4644         int i;
4645
4646         // check if we need the meshbuffers
4647         if (!vid.useinterleavedarrays)
4648                 return;
4649
4650         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4651                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4652         // TODO: upload vertex3f buffer?
4653         if (ent->animcache_vertexmesh)
4654         {
4655                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4656                 for (i = 0;i < numvertices;i++)
4657                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4658                 if (ent->animcache_svector3f)
4659                         for (i = 0;i < numvertices;i++)
4660                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4661                 if (ent->animcache_tvector3f)
4662                         for (i = 0;i < numvertices;i++)
4663                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4664                 if (ent->animcache_normal3f)
4665                         for (i = 0;i < numvertices;i++)
4666                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4667                 // TODO: upload vertexmeshbuffer?
4668         }
4669 }
4670
4671 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4672 {
4673         dp_model_t *model = ent->model;
4674         int numvertices;
4675         // see if it's already cached this frame
4676         if (ent->animcache_vertex3f)
4677         {
4678                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4679                 if (wantnormals || wanttangents)
4680                 {
4681                         if (ent->animcache_normal3f)
4682                                 wantnormals = false;
4683                         if (ent->animcache_svector3f)
4684                                 wanttangents = false;
4685                         if (wantnormals || wanttangents)
4686                         {
4687                                 numvertices = model->surfmesh.num_vertices;
4688                                 if (wantnormals)
4689                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4690                                 if (wanttangents)
4691                                 {
4692                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4694                                 }
4695                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4696                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4697                         }
4698                 }
4699         }
4700         else
4701         {
4702                 // see if this ent is worth caching
4703                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4704                         return false;
4705                 // get some memory for this entity and generate mesh data
4706                 numvertices = model->surfmesh.num_vertices;
4707                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4708                 if (wantnormals)
4709                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4710                 if (wanttangents)
4711                 {
4712                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4713                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                 }
4715                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4716                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4717         }
4718         return true;
4719 }
4720
4721 void R_AnimCache_CacheVisibleEntities(void)
4722 {
4723         int i;
4724         qboolean wantnormals = true;
4725         qboolean wanttangents = !r_showsurfaces.integer;
4726
4727         switch(vid.renderpath)
4728         {
4729         case RENDERPATH_GL20:
4730         case RENDERPATH_D3D9:
4731         case RENDERPATH_D3D10:
4732         case RENDERPATH_D3D11:
4733         case RENDERPATH_GLES2:
4734                 break;
4735         case RENDERPATH_GL11:
4736         case RENDERPATH_GL13:
4737         case RENDERPATH_GLES1:
4738                 wanttangents = false;
4739                 break;
4740         case RENDERPATH_SOFT:
4741                 break;
4742         }
4743
4744         if (r_shownormals.integer)
4745                 wanttangents = wantnormals = true;
4746
4747         // TODO: thread this
4748         // NOTE: R_PrepareRTLights() also caches entities
4749
4750         for (i = 0;i < r_refdef.scene.numentities;i++)
4751                 if (r_refdef.viewcache.entityvisible[i])
4752                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4753 }
4754
4755 //==================================================================================
4756
4757 extern cvar_t r_overheadsprites_pushback;
4758
4759 static void R_View_UpdateEntityLighting (void)
4760 {
4761         int i;
4762         entity_render_t *ent;
4763         vec3_t tempdiffusenormal, avg;
4764         vec_t f, fa, fd, fdd;
4765         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4766
4767         for (i = 0;i < r_refdef.scene.numentities;i++)
4768         {
4769                 ent = r_refdef.scene.entities[i];
4770
4771                 // skip unseen models
4772                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4773                         continue;
4774
4775                 // skip bsp models
4776                 if (ent->model && ent->model->brush.num_leafs)
4777                 {
4778                         // TODO: use modellight for r_ambient settings on world?
4779                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4780                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4781                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4782                         continue;
4783                 }
4784
4785                 // fetch the lighting from the worldmodel data
4786                 VectorClear(ent->modellight_ambient);
4787                 VectorClear(ent->modellight_diffuse);
4788                 VectorClear(tempdiffusenormal);
4789                 if (ent->flags & RENDER_LIGHT)
4790                 {
4791                         vec3_t org;
4792                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4793
4794                         // complete lightning for lit sprites
4795                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4796                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4797                         {
4798                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4799                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4800                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4801                         }
4802                         else
4803                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4804
4805                         if(ent->flags & RENDER_EQUALIZE)
4806                         {
4807                                 // first fix up ambient lighting...
4808                                 if(r_equalize_entities_minambient.value > 0)
4809                                 {
4810                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4811                                         if(fd > 0)
4812                                         {
4813                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4814                                                 if(fa < r_equalize_entities_minambient.value * fd)
4815                                                 {
4816                                                         // solve:
4817                                                         //   fa'/fd' = minambient
4818                                                         //   fa'+0.25*fd' = fa+0.25*fd
4819                                                         //   ...
4820                                                         //   fa' = fd' * minambient
4821                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4822                                                         //   ...
4823                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4824                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4825                                                         //   ...
4826                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4827                                                         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
4828                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4829                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4830                                                 }
4831                                         }
4832                                 }
4833
4834                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4835                                 {
4836                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4837                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4838                                         f = fa + 0.25 * fd;
4839                                         if(f > 0)
4840                                         {
4841                                                 // adjust brightness and saturation to target
4842                                                 avg[0] = avg[1] = avg[2] = fa / f;
4843                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4844                                                 avg[0] = avg[1] = avg[2] = fd / f;
4845                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4846                                         }
4847                                 }
4848                         }
4849                 }
4850                 else // highly rare
4851                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4852
4853                 // move the light direction into modelspace coordinates for lighting code
4854                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4855                 if(VectorLength2(ent->modellight_lightdir) == 0)
4856                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4857                 VectorNormalize(ent->modellight_lightdir);
4858         }
4859 }
4860
4861 #define MAX_LINEOFSIGHTTRACES 64
4862
4863 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4864 {
4865         int i;
4866         vec3_t boxmins, boxmaxs;
4867         vec3_t start;
4868         vec3_t end;
4869         dp_model_t *model = r_refdef.scene.worldmodel;
4870
4871         if (!model || !model->brush.TraceLineOfSight)
4872                 return true;
4873
4874         // expand the box a little
4875         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4876         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4877         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4878         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4879         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4880         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4881
4882         // return true if eye is inside enlarged box
4883         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4884                 return true;
4885
4886         // try center
4887         VectorCopy(eye, start);
4888         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4889         if (model->brush.TraceLineOfSight(model, start, end))
4890                 return true;
4891
4892         // try various random positions
4893         for (i = 0;i < numsamples;i++)
4894         {
4895                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4896                 if (model->brush.TraceLineOfSight(model, start, end))
4897                         return true;
4898         }
4899
4900         return false;
4901 }
4902
4903
4904 static void R_View_UpdateEntityVisible (void)
4905 {
4906         int i;
4907         int renderimask;
4908         int samples;
4909         entity_render_t *ent;
4910
4911         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4912                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4913                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4914                 :                                                          RENDER_EXTERIORMODEL;
4915         if (!r_drawviewmodel.integer)
4916                 renderimask |= RENDER_VIEWMODEL;
4917         if (!r_drawexteriormodel.integer)
4918                 renderimask |= RENDER_EXTERIORMODEL;
4919         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4920         {
4921                 // worldmodel can check visibility
4922                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4923                 for (i = 0;i < r_refdef.scene.numentities;i++)
4924                 {
4925                         ent = r_refdef.scene.entities[i];
4926                         if (!(ent->flags & renderimask))
4927                         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)))
4928                         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))
4929                                 r_refdef.viewcache.entityvisible[i] = true;
4930                 }
4931         }
4932         else
4933         {
4934                 // no worldmodel or it can't check visibility
4935                 for (i = 0;i < r_refdef.scene.numentities;i++)
4936                 {
4937                         ent = r_refdef.scene.entities[i];
4938                         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));
4939                 }
4940         }
4941         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4942                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4943         {
4944                 for (i = 0;i < r_refdef.scene.numentities;i++)
4945                 {
4946                         if (!r_refdef.viewcache.entityvisible[i])
4947                                 continue;
4948                         ent = r_refdef.scene.entities[i];
4949                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4950                         {
4951                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4952                                 if (samples < 0)
4953                                         continue; // temp entities do pvs only
4954                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4955                                         ent->last_trace_visibility = realtime;
4956                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4957                                         r_refdef.viewcache.entityvisible[i] = 0;
4958                         }
4959                 }
4960         }
4961 }
4962
4963 /// only used if skyrendermasked, and normally returns false
4964 int R_DrawBrushModelsSky (void)
4965 {
4966         int i, sky;
4967         entity_render_t *ent;
4968
4969         sky = false;
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->model || !ent->model->DrawSky)
4976                         continue;
4977                 ent->model->DrawSky(ent);
4978                 sky = true;
4979         }
4980         return sky;
4981 }
4982
4983 static void R_DrawNoModel(entity_render_t *ent);
4984 static void R_DrawModels(void)
4985 {
4986         int i;
4987         entity_render_t *ent;
4988
4989         for (i = 0;i < r_refdef.scene.numentities;i++)
4990         {
4991                 if (!r_refdef.viewcache.entityvisible[i])
4992                         continue;
4993                 ent = r_refdef.scene.entities[i];
4994                 r_refdef.stats.entities++;
4995                 /*
4996                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4997                 {
4998                         vec3_t f, l, u, o;
4999                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5000                         Con_Printf("R_DrawModels\n");
5001                         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]);
5002                         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);
5003                         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);
5004                 }
5005                 */
5006                 if (ent->model && ent->model->Draw != NULL)
5007                         ent->model->Draw(ent);
5008                 else
5009                         R_DrawNoModel(ent);
5010         }
5011 }
5012
5013 static void R_DrawModelsDepth(void)
5014 {
5015         int i;
5016         entity_render_t *ent;
5017
5018         for (i = 0;i < r_refdef.scene.numentities;i++)
5019         {
5020                 if (!r_refdef.viewcache.entityvisible[i])
5021                         continue;
5022                 ent = r_refdef.scene.entities[i];
5023                 if (ent->model && ent->model->DrawDepth != NULL)
5024                         ent->model->DrawDepth(ent);
5025         }
5026 }
5027
5028 static void R_DrawModelsDebug(void)
5029 {
5030         int i;
5031         entity_render_t *ent;
5032
5033         for (i = 0;i < r_refdef.scene.numentities;i++)
5034         {
5035                 if (!r_refdef.viewcache.entityvisible[i])
5036                         continue;
5037                 ent = r_refdef.scene.entities[i];
5038                 if (ent->model && ent->model->DrawDebug != NULL)
5039                         ent->model->DrawDebug(ent);
5040         }
5041 }
5042
5043 static void R_DrawModelsAddWaterPlanes(void)
5044 {
5045         int i;
5046         entity_render_t *ent;
5047
5048         for (i = 0;i < r_refdef.scene.numentities;i++)
5049         {
5050                 if (!r_refdef.viewcache.entityvisible[i])
5051                         continue;
5052                 ent = r_refdef.scene.entities[i];
5053                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5054                         ent->model->DrawAddWaterPlanes(ent);
5055         }
5056 }
5057
5058 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5059 {
5060         if (r_hdr_irisadaptation.integer)
5061         {
5062                 vec3_t ambient;
5063                 vec3_t diffuse;
5064                 vec3_t diffusenormal;
5065                 vec_t brightness;
5066                 vec_t goal;
5067                 vec_t current;
5068                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5069                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5070                 brightness = max(0.0000001f, brightness);
5071                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5072                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5073                 current = r_hdr_irisadaptation_value.value;
5074                 if (current < goal)
5075                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5076                 else if (current > goal)
5077                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5078                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5079                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5080         }
5081         else if (r_hdr_irisadaptation_value.value != 1.0f)
5082                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5083 }
5084
5085 static void R_View_SetFrustum(const int *scissor)
5086 {
5087         int i;
5088         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5089         vec3_t forward, left, up, origin, v;
5090
5091         if(scissor)
5092         {
5093                 // flipped x coordinates (because x points left here)
5094                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5095                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096
5097                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5098                 switch(vid.renderpath)
5099                 {
5100                         case RENDERPATH_D3D9:
5101                         case RENDERPATH_D3D10:
5102                         case RENDERPATH_D3D11:
5103                                 // non-flipped y coordinates
5104                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 break;
5107                         case RENDERPATH_SOFT:
5108                         case RENDERPATH_GL11:
5109                         case RENDERPATH_GL13:
5110                         case RENDERPATH_GL20:
5111                         case RENDERPATH_GLES1:
5112                         case RENDERPATH_GLES2:
5113                                 // non-flipped y coordinates
5114                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5115                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 break;
5117                 }
5118         }
5119
5120         // we can't trust r_refdef.view.forward and friends in reflected scenes
5121         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5122
5123 #if 0
5124         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5125         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5126         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5127         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5128         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5129         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5130         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5131         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5132         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5133         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5134         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5135         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5136 #endif
5137
5138 #if 0
5139         zNear = r_refdef.nearclip;
5140         nudge = 1.0 - 1.0 / (1<<23);
5141         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5142         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5144         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5145         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5146         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5148         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5149 #endif
5150
5151
5152
5153 #if 0
5154         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5155         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5156         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5157         r_refdef.view.frustum[0].dist = m[15] - m[12];
5158
5159         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5160         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5161         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5162         r_refdef.view.frustum[1].dist = m[15] + m[12];
5163
5164         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5165         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5166         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5167         r_refdef.view.frustum[2].dist = m[15] - m[13];
5168
5169         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5170         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5171         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5172         r_refdef.view.frustum[3].dist = m[15] + m[13];
5173
5174         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5175         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5176         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5177         r_refdef.view.frustum[4].dist = m[15] - m[14];
5178
5179         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5180         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5181         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5182         r_refdef.view.frustum[5].dist = m[15] + m[14];
5183 #endif
5184
5185         if (r_refdef.view.useperspective)
5186         {
5187                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5188                 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]);
5189                 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]);
5190                 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]);
5191                 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]);
5192
5193                 // then the normals from the corners relative to origin
5194                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5195                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5198
5199                 // in a NORMAL view, forward cross left == up
5200                 // in a REFLECTED view, forward cross left == down
5201                 // so our cross products above need to be adjusted for a left handed coordinate system
5202                 CrossProduct(forward, left, v);
5203                 if(DotProduct(v, up) < 0)
5204                 {
5205                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5206                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5207                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5208                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5209                 }
5210
5211                 // Leaving those out was a mistake, those were in the old code, and they
5212                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5213                 // I couldn't reproduce it after adding those normalizations. --blub
5214                 VectorNormalize(r_refdef.view.frustum[0].normal);
5215                 VectorNormalize(r_refdef.view.frustum[1].normal);
5216                 VectorNormalize(r_refdef.view.frustum[2].normal);
5217                 VectorNormalize(r_refdef.view.frustum[3].normal);
5218
5219                 // make the corners absolute
5220                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5221                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5222                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5223                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5224
5225                 // one more normal
5226                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5227
5228                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5229                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5230                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5231                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5232                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5233         }
5234         else
5235         {
5236                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5237                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5238                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5239                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5240                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5241                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5242                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5244                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5246         }
5247         r_refdef.view.numfrustumplanes = 5;
5248
5249         if (r_refdef.view.useclipplane)
5250         {
5251                 r_refdef.view.numfrustumplanes = 6;
5252                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5253         }
5254
5255         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5256                 PlaneClassify(r_refdef.view.frustum + i);
5257
5258         // LordHavoc: note to all quake engine coders, Quake had a special case
5259         // for 90 degrees which assumed a square view (wrong), so I removed it,
5260         // Quake2 has it disabled as well.
5261
5262         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5263         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5264         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5265         //PlaneClassify(&frustum[0]);
5266
5267         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5268         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5269         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5270         //PlaneClassify(&frustum[1]);
5271
5272         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5273         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5274         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5275         //PlaneClassify(&frustum[2]);
5276
5277         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5278         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5279         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5280         //PlaneClassify(&frustum[3]);
5281
5282         // nearclip plane
5283         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5284         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5285         //PlaneClassify(&frustum[4]);
5286 }
5287
5288 void R_View_UpdateWithScissor(const int *myscissor)
5289 {
5290         R_Main_ResizeViewCache();
5291         R_View_SetFrustum(myscissor);
5292         R_View_WorldVisibility(r_refdef.view.useclipplane);
5293         R_View_UpdateEntityVisible();
5294         R_View_UpdateEntityLighting();
5295 }
5296
5297 void R_View_Update(void)
5298 {
5299         R_Main_ResizeViewCache();
5300         R_View_SetFrustum(NULL);
5301         R_View_WorldVisibility(r_refdef.view.useclipplane);
5302         R_View_UpdateEntityVisible();
5303         R_View_UpdateEntityLighting();
5304 }
5305
5306 float viewscalefpsadjusted = 1.0f;
5307
5308 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5309 {
5310         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5311         scale = bound(0.03125f, scale, 1.0f);
5312         *outwidth = (int)ceil(width * scale);
5313         *outheight = (int)ceil(height * scale);
5314 }
5315
5316 void R_Mesh_SetMainRenderTargets(void)
5317 {
5318         if (r_bloomstate.fbo_framebuffer)
5319                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5320         else
5321                 R_Mesh_ResetRenderTargets();
5322 }
5323
5324 void R_SetupView(qboolean allowwaterclippingplane)
5325 {
5326         const float *customclipplane = NULL;
5327         float plane[4];
5328         int scaledwidth, scaledheight;
5329         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5330         {
5331                 // LordHavoc: couldn't figure out how to make this approach the
5332                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5333                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5334                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5335                         dist = r_refdef.view.clipplane.dist;
5336                 plane[0] = r_refdef.view.clipplane.normal[0];
5337                 plane[1] = r_refdef.view.clipplane.normal[1];
5338                 plane[2] = r_refdef.view.clipplane.normal[2];
5339                 plane[3] = -dist;
5340                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5341         }
5342
5343         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5344         if (!r_refdef.view.useperspective)
5345                 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);
5346         else if (vid.stencil && r_useinfinitefarclip.integer)
5347                 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);
5348         else
5349                 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);
5350         R_Mesh_SetMainRenderTargets();
5351         R_SetViewport(&r_refdef.view.viewport);
5352         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5353         {
5354                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5355                 float screenplane[4];
5356                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5357                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5358                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5359                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5360                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5361         }
5362 }
5363
5364 void R_EntityMatrix(const matrix4x4_t *matrix)
5365 {
5366         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5367         {
5368                 gl_modelmatrixchanged = false;
5369                 gl_modelmatrix = *matrix;
5370                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5371                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5372                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5373                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5374                 CHECKGLERROR
5375                 switch(vid.renderpath)
5376                 {
5377                 case RENDERPATH_D3D9:
5378 #ifdef SUPPORTD3D
5379                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5380                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5381 #endif
5382                         break;
5383                 case RENDERPATH_D3D10:
5384                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5385                         break;
5386                 case RENDERPATH_D3D11:
5387                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5388                         break;
5389                 case RENDERPATH_GL11:
5390                 case RENDERPATH_GL13:
5391                 case RENDERPATH_GLES1:
5392                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5393                         break;
5394                 case RENDERPATH_SOFT:
5395                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5396                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5397                         break;
5398                 case RENDERPATH_GL20:
5399                 case RENDERPATH_GLES2:
5400                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5401                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5402                         break;
5403                 }
5404         }
5405 }
5406
5407 void R_ResetViewRendering2D(void)
5408 {
5409         r_viewport_t viewport;
5410         DrawQ_Finish();
5411
5412         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5413         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);
5414         R_Mesh_ResetRenderTargets();
5415         R_SetViewport(&viewport);
5416         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5417         GL_Color(1, 1, 1, 1);
5418         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5419         GL_BlendFunc(GL_ONE, GL_ZERO);
5420         GL_ScissorTest(false);
5421         GL_DepthMask(false);
5422         GL_DepthRange(0, 1);
5423         GL_DepthTest(false);
5424         GL_DepthFunc(GL_LEQUAL);
5425         R_EntityMatrix(&identitymatrix);
5426         R_Mesh_ResetTextureState();
5427         GL_PolygonOffset(0, 0);
5428         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5429         switch(vid.renderpath)
5430         {
5431         case RENDERPATH_GL11:
5432         case RENDERPATH_GL13:
5433         case RENDERPATH_GL20:
5434         case RENDERPATH_GLES1:
5435         case RENDERPATH_GLES2:
5436                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5437                 break;
5438         case RENDERPATH_D3D9:
5439         case RENDERPATH_D3D10:
5440         case RENDERPATH_D3D11:
5441         case RENDERPATH_SOFT:
5442                 break;
5443         }
5444         GL_CullFace(GL_NONE);
5445 }
5446
5447 void R_ResetViewRendering3D(void)
5448 {
5449         DrawQ_Finish();
5450
5451         R_SetupView(true);
5452         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5453         GL_Color(1, 1, 1, 1);
5454         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5455         GL_BlendFunc(GL_ONE, GL_ZERO);
5456         GL_ScissorTest(true);
5457         GL_DepthMask(true);
5458         GL_DepthRange(0, 1);
5459         GL_DepthTest(true);
5460         GL_DepthFunc(GL_LEQUAL);
5461         R_EntityMatrix(&identitymatrix);
5462         R_Mesh_ResetTextureState();
5463         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5464         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5465         switch(vid.renderpath)
5466         {
5467         case RENDERPATH_GL11:
5468         case RENDERPATH_GL13:
5469         case RENDERPATH_GL20:
5470         case RENDERPATH_GLES1:
5471         case RENDERPATH_GLES2:
5472                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5473                 break;
5474         case RENDERPATH_D3D9:
5475         case RENDERPATH_D3D10:
5476         case RENDERPATH_D3D11:
5477         case RENDERPATH_SOFT:
5478                 break;
5479         }
5480         GL_CullFace(r_refdef.view.cullface_back);
5481 }
5482
5483 /*
5484 ================
5485 R_RenderView_UpdateViewVectors
5486 ================
5487 */
5488 static void R_RenderView_UpdateViewVectors(void)
5489 {
5490         // break apart the view matrix into vectors for various purposes
5491         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5492         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5493         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5494         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5495         // make an inverted copy of the view matrix for tracking sprites
5496         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5497 }
5498
5499 void R_RenderScene(void);
5500 void R_RenderWaterPlanes(void);
5501
5502 static void R_Water_StartFrame(void)
5503 {
5504         int i;
5505         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5506         r_waterstate_waterplane_t *p;
5507
5508         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5509                 return;
5510
5511         switch(vid.renderpath)
5512         {
5513         case RENDERPATH_GL20:
5514         case RENDERPATH_D3D9:
5515         case RENDERPATH_D3D10:
5516         case RENDERPATH_D3D11:
5517         case RENDERPATH_SOFT:
5518         case RENDERPATH_GLES2:
5519                 break;
5520         case RENDERPATH_GL11:
5521         case RENDERPATH_GL13:
5522         case RENDERPATH_GLES1:
5523                 return;
5524         }
5525
5526         // set waterwidth and waterheight to the water resolution that will be
5527         // used (often less than the screen resolution for faster rendering)
5528         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5529
5530         // calculate desired texture sizes
5531         // can't use water if the card does not support the texture size
5532         if (!r_water.integer || r_showsurfaces.integer)
5533                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5534         else if (vid.support.arb_texture_non_power_of_two)
5535         {
5536                 texturewidth = waterwidth;
5537                 textureheight = waterheight;
5538                 camerawidth = waterwidth;
5539                 cameraheight = waterheight;
5540         }
5541         else
5542         {
5543                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5544                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5545                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5546                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5547         }
5548
5549         // allocate textures as needed
5550         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5551         {
5552                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5553                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5554                 {
5555                         if (p->texture_refraction)
5556                                 R_FreeTexture(p->texture_refraction);
5557                         p->texture_refraction = NULL;
5558                         if (p->texture_reflection)
5559                                 R_FreeTexture(p->texture_reflection);
5560                         p->texture_reflection = NULL;
5561                         if (p->texture_camera)
5562                                 R_FreeTexture(p->texture_camera);
5563                         p->texture_camera = NULL;
5564                 }
5565                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5566                 r_waterstate.texturewidth = texturewidth;
5567                 r_waterstate.textureheight = textureheight;
5568                 r_waterstate.camerawidth = camerawidth;
5569                 r_waterstate.cameraheight = cameraheight;
5570         }
5571
5572         if (r_waterstate.texturewidth)
5573         {
5574                 int scaledwidth, scaledheight;
5575
5576                 r_waterstate.enabled = true;
5577
5578                 // when doing a reduced render (HDR) we want to use a smaller area
5579                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5580                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5581                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5582
5583                 // set up variables that will be used in shader setup
5584                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5585                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5586                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5587                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5588         }
5589
5590         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5591         r_waterstate.numwaterplanes = 0;
5592 }
5593
5594 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5595 {
5596         int triangleindex, planeindex;
5597         const int *e;
5598         vec3_t vert[3];
5599         vec3_t normal;
5600         vec3_t center;
5601         mplane_t plane;
5602         r_waterstate_waterplane_t *p;
5603         texture_t *t = R_GetCurrentTexture(surface->texture);
5604
5605         // just use the first triangle with a valid normal for any decisions
5606         VectorClear(normal);
5607         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5608         {
5609                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5610                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5611                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5612                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5613                 if (VectorLength2(normal) >= 0.001)
5614                         break;
5615         }
5616
5617         VectorCopy(normal, plane.normal);
5618         VectorNormalize(plane.normal);
5619         plane.dist = DotProduct(vert[0], plane.normal);
5620         PlaneClassify(&plane);
5621         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5622         {
5623                 // skip backfaces (except if nocullface is set)
5624                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5625                         return;
5626                 VectorNegate(plane.normal, plane.normal);
5627                 plane.dist *= -1;
5628                 PlaneClassify(&plane);
5629         }
5630
5631
5632         // find a matching plane if there is one
5633         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5634                 if(p->camera_entity == t->camera_entity)
5635                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5636                                 break;
5637         if (planeindex >= r_waterstate.maxwaterplanes)
5638                 return; // nothing we can do, out of planes
5639
5640         // if this triangle does not fit any known plane rendered this frame, add one
5641         if (planeindex >= r_waterstate.numwaterplanes)
5642         {
5643                 // store the new plane
5644                 r_waterstate.numwaterplanes++;
5645                 p->plane = plane;
5646                 // clear materialflags and pvs
5647                 p->materialflags = 0;
5648                 p->pvsvalid = false;
5649                 p->camera_entity = t->camera_entity;
5650                 VectorCopy(surface->mins, p->mins);
5651                 VectorCopy(surface->maxs, p->maxs);
5652         }
5653         else
5654         {
5655                 // merge mins/maxs
5656                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5657                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5658                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5659                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5660                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5661                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5662         }
5663         // merge this surface's materialflags into the waterplane
5664         p->materialflags |= t->currentmaterialflags;
5665         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5666         {
5667                 // merge this surface's PVS into the waterplane
5668                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5669                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5670                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5671                 {
5672                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5673                         p->pvsvalid = true;
5674                 }
5675         }
5676 }
5677
5678 extern cvar_t r_drawparticles;
5679 extern cvar_t r_drawdecals;
5680
5681 static void R_Water_ProcessPlanes(void)
5682 {
5683         int myscissor[4];
5684         r_refdef_view_t originalview;
5685         r_refdef_view_t myview;
5686         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;
5687         r_waterstate_waterplane_t *p;
5688         vec3_t visorigin;
5689
5690         originalview = r_refdef.view;
5691
5692         // lowquality hack, temporarily shut down some cvars and restore afterwards
5693         qualityreduction = r_water_lowquality.integer;
5694         if (qualityreduction > 0)
5695         {
5696                 if (qualityreduction >= 1)
5697                 {
5698                         old_r_shadows = r_shadows.integer;
5699                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5700                         old_r_dlight = r_shadow_realtime_dlight.integer;
5701                         Cvar_SetValueQuick(&r_shadows, 0);
5702                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5703                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5704                 }
5705                 if (qualityreduction >= 2)
5706                 {
5707                         old_r_dynamic = r_dynamic.integer;
5708                         old_r_particles = r_drawparticles.integer;
5709                         old_r_decals = r_drawdecals.integer;
5710                         Cvar_SetValueQuick(&r_dynamic, 0);
5711                         Cvar_SetValueQuick(&r_drawparticles, 0);
5712                         Cvar_SetValueQuick(&r_drawdecals, 0);
5713                 }
5714         }
5715
5716         // make sure enough textures are allocated
5717         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5718         {
5719                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5720                 {
5721                         if (!p->texture_refraction)
5722                                 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);
5723                         if (!p->texture_refraction)
5724                                 goto error;
5725                 }
5726                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5727                 {
5728                         if (!p->texture_camera)
5729                                 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);
5730                         if (!p->texture_camera)
5731                                 goto error;
5732                 }
5733
5734                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5735                 {
5736                         if (!p->texture_reflection)
5737                                 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);
5738                         if (!p->texture_reflection)
5739                                 goto error;
5740                 }
5741         }
5742
5743         // render views
5744         r_refdef.view = originalview;
5745         r_refdef.view.showdebug = false;
5746         r_refdef.view.width = r_waterstate.waterwidth;
5747         r_refdef.view.height = r_waterstate.waterheight;
5748         r_refdef.view.useclipplane = true;
5749         myview = r_refdef.view;
5750         r_waterstate.renderingscene = true;
5751         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5752         {
5753                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5754                 {
5755                         r_refdef.view = myview;
5756                         if(r_water_scissormode.integer)
5757                         {
5758                                 R_SetupView(true);
5759                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5760                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5761                         }
5762
5763                         // render reflected scene and copy into texture
5764                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5765                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5766                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5767                         r_refdef.view.clipplane = p->plane;
5768                         // reverse the cullface settings for this render
5769                         r_refdef.view.cullface_front = GL_FRONT;
5770                         r_refdef.view.cullface_back = GL_BACK;
5771                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5772                         {
5773                                 r_refdef.view.usecustompvs = true;
5774                                 if (p->pvsvalid)
5775                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5776                                 else
5777                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5778                         }
5779
5780                         R_ResetViewRendering3D();
5781                         R_ClearScreen(r_refdef.fogenabled);
5782                         if(r_water_scissormode.integer & 2)
5783                                 R_View_UpdateWithScissor(myscissor);
5784                         else
5785                                 R_View_Update();
5786                         if(r_water_scissormode.integer & 1)
5787                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5788                         R_RenderScene();
5789
5790                         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);
5791                 }
5792
5793                 // render the normal view scene and copy into texture
5794                 // (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)
5795                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5796                 {
5797                         r_refdef.view = myview;
5798                         if(r_water_scissormode.integer)
5799                         {
5800                                 R_SetupView(true);
5801                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5802                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5803                         }
5804
5805                         r_waterstate.renderingrefraction = true;
5806
5807                         r_refdef.view.clipplane = p->plane;
5808                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5809                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5810
5811                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5812                         {
5813                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5814                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5815                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5816                                 R_RenderView_UpdateViewVectors();
5817                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5818                                 {
5819                                         r_refdef.view.usecustompvs = true;
5820                                         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);
5821                                 }
5822                         }
5823
5824                         PlaneClassify(&r_refdef.view.clipplane);
5825
5826                         R_ResetViewRendering3D();
5827                         R_ClearScreen(r_refdef.fogenabled);
5828                         if(r_water_scissormode.integer & 2)
5829                                 R_View_UpdateWithScissor(myscissor);
5830                         else
5831                                 R_View_Update();
5832                         if(r_water_scissormode.integer & 1)
5833                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5834                         R_RenderScene();
5835
5836                         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);
5837                         r_waterstate.renderingrefraction = false;
5838                 }
5839                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5840                 {
5841                         r_refdef.view = myview;
5842
5843                         r_refdef.view.clipplane = p->plane;
5844                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5845                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5846
5847                         r_refdef.view.width = r_waterstate.camerawidth;
5848                         r_refdef.view.height = r_waterstate.cameraheight;
5849                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5850                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5851
5852                         if(p->camera_entity)
5853                         {
5854                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5855                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5856                         }
5857
5858                         // note: all of the view is used for displaying... so
5859                         // there is no use in scissoring
5860
5861                         // reverse the cullface settings for this render
5862                         r_refdef.view.cullface_front = GL_FRONT;
5863                         r_refdef.view.cullface_back = GL_BACK;
5864                         // also reverse the view matrix
5865                         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
5866                         R_RenderView_UpdateViewVectors();
5867                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5868                         {
5869                                 r_refdef.view.usecustompvs = true;
5870                                 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);
5871                         }
5872                         
5873                         // camera needs no clipplane
5874                         r_refdef.view.useclipplane = false;
5875
5876                         PlaneClassify(&r_refdef.view.clipplane);
5877
5878                         R_ResetViewRendering3D();
5879                         R_ClearScreen(r_refdef.fogenabled);
5880                         R_View_Update();
5881                         R_RenderScene();
5882
5883                         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);
5884                         r_waterstate.renderingrefraction = false;
5885                 }
5886
5887         }
5888         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5889         r_waterstate.renderingscene = false;
5890         r_refdef.view = originalview;
5891         R_ResetViewRendering3D();
5892         R_ClearScreen(r_refdef.fogenabled);
5893         R_View_Update();
5894         goto finish;
5895 error:
5896         r_refdef.view = originalview;
5897         r_waterstate.renderingscene = false;
5898         Cvar_SetValueQuick(&r_water, 0);
5899         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5900 finish:
5901         // lowquality hack, restore cvars
5902         if (qualityreduction > 0)
5903         {
5904                 if (qualityreduction >= 1)
5905                 {
5906                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5907                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5908                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5909                 }
5910                 if (qualityreduction >= 2)
5911                 {
5912                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5913                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5914                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5915                 }
5916         }
5917 }
5918
5919 void R_Bloom_StartFrame(void)
5920 {
5921         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5922         int viewwidth, viewheight;
5923         textype_t textype;
5924
5925         if (r_viewscale_fpsscaling.integer)
5926         {
5927                 double actualframetime;
5928                 double targetframetime;
5929                 double adjust;
5930                 actualframetime = r_refdef.lastdrawscreentime;
5931                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5932                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5933                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5934                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5935                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5936                 viewscalefpsadjusted += adjust;
5937                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5938         }
5939         else
5940                 viewscalefpsadjusted = 1.0f;
5941
5942         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5943
5944         switch(vid.renderpath)
5945         {
5946         case RENDERPATH_GL20:
5947         case RENDERPATH_D3D9:
5948         case RENDERPATH_D3D10:
5949         case RENDERPATH_D3D11:
5950         case RENDERPATH_SOFT:
5951         case RENDERPATH_GLES2:
5952                 break;
5953         case RENDERPATH_GL11:
5954         case RENDERPATH_GL13:
5955         case RENDERPATH_GLES1:
5956                 return;
5957         }
5958
5959         // set bloomwidth and bloomheight to the bloom resolution that will be
5960         // used (often less than the screen resolution for faster rendering)
5961         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5962         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5963         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5964         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5965         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5966
5967         // calculate desired texture sizes
5968         if (vid.support.arb_texture_non_power_of_two)
5969         {
5970                 screentexturewidth = vid.width;
5971                 screentextureheight = vid.height;
5972                 bloomtexturewidth = r_bloomstate.bloomwidth;
5973                 bloomtextureheight = r_bloomstate.bloomheight;
5974         }
5975         else
5976         {
5977                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5978                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5979                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5980                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5981         }
5982
5983         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))
5984         {
5985                 Cvar_SetValueQuick(&r_hdr, 0);
5986                 Cvar_SetValueQuick(&r_bloom, 0);
5987                 Cvar_SetValueQuick(&r_motionblur, 0);
5988                 Cvar_SetValueQuick(&r_damageblur, 0);
5989         }
5990
5991         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)
5992                 screentexturewidth = screentextureheight = 0;
5993         if (!r_hdr.integer && !r_bloom.integer)
5994                 bloomtexturewidth = bloomtextureheight = 0;
5995
5996         textype = TEXTYPE_COLORBUFFER;
5997         switch (vid.renderpath)
5998         {
5999         case RENDERPATH_GL20:
6000         case RENDERPATH_GLES2:
6001                 if (vid.support.ext_framebuffer_object)
6002                 {
6003                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6004                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6005                 }
6006                 break;
6007         case RENDERPATH_GL11:
6008         case RENDERPATH_GL13:
6009         case RENDERPATH_GLES1:
6010         case RENDERPATH_D3D9:
6011         case RENDERPATH_D3D10:
6012         case RENDERPATH_D3D11:
6013         case RENDERPATH_SOFT:
6014                 break;
6015         }
6016
6017         // allocate textures as needed
6018         if (r_bloomstate.screentexturewidth != screentexturewidth
6019          || r_bloomstate.screentextureheight != screentextureheight
6020          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6021          || r_bloomstate.bloomtextureheight != bloomtextureheight
6022          || r_bloomstate.texturetype != textype
6023          || r_bloomstate.viewfbo != r_viewfbo.integer)
6024         {
6025                 if (r_bloomstate.texture_bloom)
6026                         R_FreeTexture(r_bloomstate.texture_bloom);
6027                 r_bloomstate.texture_bloom = NULL;
6028                 if (r_bloomstate.texture_screen)
6029                         R_FreeTexture(r_bloomstate.texture_screen);
6030                 r_bloomstate.texture_screen = NULL;
6031                 if (r_bloomstate.fbo_framebuffer)
6032                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6033                 r_bloomstate.fbo_framebuffer = 0;
6034                 if (r_bloomstate.texture_framebuffercolor)
6035                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6036                 r_bloomstate.texture_framebuffercolor = NULL;
6037                 if (r_bloomstate.texture_framebufferdepth)
6038                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6039                 r_bloomstate.texture_framebufferdepth = NULL;
6040                 r_bloomstate.screentexturewidth = screentexturewidth;
6041                 r_bloomstate.screentextureheight = screentextureheight;
6042                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6043                         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);
6044                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6045                 {
6046                         // FIXME: choose depth bits based on a cvar
6047                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6048                         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);
6049                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6050                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6051 #ifndef USE_GLES2
6052                         // render depth into one texture and normalmap into the other
6053                         if (qglDrawBuffer)
6054                         {
6055                                 int status;
6056                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6057                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6058                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6059                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6060                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6061                         }
6062 #endif
6063                 }
6064                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6065                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6066                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6067                         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);
6068                 r_bloomstate.viewfbo = r_viewfbo.integer;
6069                 r_bloomstate.texturetype = textype;
6070         }
6071
6072         // when doing a reduced render (HDR) we want to use a smaller area
6073         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6074         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6075         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6076         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6077         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6078
6079         // set up a texcoord array for the full resolution screen image
6080         // (we have to keep this around to copy back during final render)
6081         r_bloomstate.screentexcoord2f[0] = 0;
6082         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6083         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6084         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6085         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6086         r_bloomstate.screentexcoord2f[5] = 0;
6087         r_bloomstate.screentexcoord2f[6] = 0;
6088         r_bloomstate.screentexcoord2f[7] = 0;
6089
6090         // set up a texcoord array for the reduced resolution bloom image
6091         // (which will be additive blended over the screen image)
6092         r_bloomstate.bloomtexcoord2f[0] = 0;
6093         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6094         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6095         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6096         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6097         r_bloomstate.bloomtexcoord2f[5] = 0;
6098         r_bloomstate.bloomtexcoord2f[6] = 0;
6099         r_bloomstate.bloomtexcoord2f[7] = 0;
6100
6101         switch(vid.renderpath)
6102         {
6103         case RENDERPATH_GL11:
6104         case RENDERPATH_GL13:
6105         case RENDERPATH_GL20:
6106         case RENDERPATH_SOFT:
6107         case RENDERPATH_GLES1:
6108         case RENDERPATH_GLES2:
6109                 break;
6110         case RENDERPATH_D3D9:
6111         case RENDERPATH_D3D10:
6112         case RENDERPATH_D3D11:
6113                 {
6114                         int i;
6115                         for (i = 0;i < 4;i++)
6116                         {
6117                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6118                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6119                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6120                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6121                         }
6122                 }
6123                 break;
6124         }
6125
6126         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6127         {
6128                 r_bloomstate.enabled = true;
6129                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6130         }
6131
6132         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);
6133
6134         if (r_bloomstate.fbo_framebuffer)
6135                 r_refdef.view.clear = true;
6136 }
6137
6138 void R_Bloom_CopyBloomTexture(float colorscale)
6139 {
6140         r_refdef.stats.bloom++;
6141
6142         // scale down screen texture to the bloom texture size
6143         CHECKGLERROR
6144         R_Mesh_SetMainRenderTargets();
6145         R_SetViewport(&r_bloomstate.viewport);
6146         GL_BlendFunc(GL_ONE, GL_ZERO);
6147         GL_Color(colorscale, colorscale, colorscale, 1);
6148         // 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...
6149         switch(vid.renderpath)
6150         {
6151         case RENDERPATH_GL11:
6152         case RENDERPATH_GL13:
6153         case RENDERPATH_GL20:
6154         case RENDERPATH_GLES1:
6155         case RENDERPATH_GLES2:
6156         case RENDERPATH_SOFT:
6157                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6158                 break;
6159         case RENDERPATH_D3D9:
6160         case RENDERPATH_D3D10:
6161         case RENDERPATH_D3D11:
6162                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6163                 break;
6164         }
6165         // TODO: do boxfilter scale-down in shader?
6166         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6167         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6169
6170         // we now have a bloom image in the framebuffer
6171         // copy it into the bloom image texture for later processing
6172         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);
6173         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6174 }
6175
6176 void R_Bloom_CopyHDRTexture(void)
6177 {
6178         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);
6179         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6180 }
6181
6182 void R_Bloom_MakeTexture(void)
6183 {
6184         int x, range, dir;
6185         float xoffset, yoffset, r, brighten;
6186
6187         r_refdef.stats.bloom++;
6188
6189         R_ResetViewRendering2D();
6190
6191         // we have a bloom image in the framebuffer
6192         CHECKGLERROR
6193         R_SetViewport(&r_bloomstate.viewport);
6194
6195         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6196         {
6197                 x *= 2;
6198                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6199                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6200                 GL_Color(r,r,r,1);
6201                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6202                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6203                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6204                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6205
6206                 // copy the vertically blurred bloom view to a texture
6207                 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);
6208                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6209         }
6210
6211         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6212         brighten = r_bloom_brighten.value;
6213         if (r_bloomstate.hdr)
6214                 brighten *= r_hdr_range.value;
6215         brighten = sqrt(brighten);
6216         if(range >= 1)
6217                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6218         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6219
6220         for (dir = 0;dir < 2;dir++)
6221         {
6222                 // blend on at multiple vertical offsets to achieve a vertical blur
6223                 // TODO: do offset blends using GLSL
6224                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6225                 GL_BlendFunc(GL_ONE, GL_ZERO);
6226                 for (x = -range;x <= range;x++)
6227                 {
6228                         if (!dir){xoffset = 0;yoffset = x;}
6229                         else {xoffset = x;yoffset = 0;}
6230                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6231                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6232                         // compute a texcoord array with the specified x and y offset
6233                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6234                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6235                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6236                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6237                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6238                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6239                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6240                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6241                         // this r value looks like a 'dot' particle, fading sharply to
6242                         // black at the edges
6243                         // (probably not realistic but looks good enough)
6244                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6245                         //r = brighten/(range*2+1);
6246                         r = brighten / (range * 2 + 1);
6247                         if(range >= 1)
6248                                 r *= (1 - x*x/(float)(range*range));
6249                         GL_Color(r, r, r, 1);
6250                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6251                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6253                         GL_BlendFunc(GL_ONE, GL_ONE);
6254                 }
6255
6256                 // copy the vertically blurred bloom view to a texture
6257                 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);
6258                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6259         }
6260 }
6261
6262 void R_HDR_RenderBloomTexture(void)
6263 {
6264         int oldwidth, oldheight;
6265         float oldcolorscale;
6266         qboolean oldwaterstate;
6267
6268         oldwaterstate = r_waterstate.enabled;
6269         oldcolorscale = r_refdef.view.colorscale;
6270         oldwidth = r_refdef.view.width;
6271         oldheight = r_refdef.view.height;
6272         r_refdef.view.width = r_bloomstate.bloomwidth;
6273         r_refdef.view.height = r_bloomstate.bloomheight;
6274
6275         if(r_hdr.integer < 2)
6276                 r_waterstate.enabled = false;
6277
6278         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6279         // TODO: add exposure compensation features
6280         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6281
6282         r_refdef.view.showdebug = false;
6283         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6284
6285         R_ResetViewRendering3D();
6286
6287         R_ClearScreen(r_refdef.fogenabled);
6288         if (r_timereport_active)
6289                 R_TimeReport("HDRclear");
6290
6291         R_View_Update();
6292         if (r_timereport_active)
6293                 R_TimeReport("visibility");
6294
6295         // only do secondary renders with HDR if r_hdr is 2 or higher
6296         r_waterstate.numwaterplanes = 0;
6297         if (r_waterstate.enabled)
6298                 R_RenderWaterPlanes();
6299
6300         r_refdef.view.showdebug = true;
6301         R_RenderScene();
6302         r_waterstate.numwaterplanes = 0;
6303
6304         R_ResetViewRendering2D();
6305
6306         R_Bloom_CopyHDRTexture();
6307         R_Bloom_MakeTexture();
6308
6309         // restore the view settings
6310         r_waterstate.enabled = oldwaterstate;
6311         r_refdef.view.width = oldwidth;
6312         r_refdef.view.height = oldheight;
6313         r_refdef.view.colorscale = oldcolorscale;
6314
6315         R_ResetViewRendering3D();
6316
6317         R_ClearScreen(r_refdef.fogenabled);
6318         if (r_timereport_active)
6319                 R_TimeReport("viewclear");
6320 }
6321
6322 static void R_BlendView(void)
6323 {
6324         unsigned int permutation;
6325         float uservecs[4][4];
6326
6327         switch (vid.renderpath)
6328         {
6329         case RENDERPATH_GL20:
6330         case RENDERPATH_D3D9:
6331         case RENDERPATH_D3D10:
6332         case RENDERPATH_D3D11:
6333         case RENDERPATH_SOFT:
6334         case RENDERPATH_GLES2:
6335                 permutation =
6336                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6337                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6338                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6339                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6340                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6341
6342                 if (r_bloomstate.texture_screen)
6343                 {
6344                         // make sure the buffer is available
6345                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6346
6347                         R_ResetViewRendering2D();
6348                         R_Mesh_SetMainRenderTargets();
6349
6350                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6351                         {
6352                                 // declare variables
6353                                 float blur_factor, blur_mouseaccel, blur_velocity;
6354                                 static float blur_average; 
6355                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6356
6357                                 // set a goal for the factoring
6358                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6359                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6360                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6361                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6362                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6363                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6364
6365                                 // from the goal, pick an averaged value between goal and last value
6366                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6367                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6368                                 
6369                                 // enforce minimum amount of blur 
6370                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6371                                 
6372                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6373
6374                                 // calculate values into a standard alpha
6375                                 cl.motionbluralpha = 1 - exp(-
6376                                                 (
6377                                                  (r_motionblur.value * blur_factor / 80)
6378                                                  +
6379                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6380                                                 )
6381                                                 /
6382                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6383                                           );
6384                                 
6385                                 // randomization for the blur value to combat persistent ghosting
6386                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6387                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6388                                 
6389                                 // apply the blur
6390                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6391                                 {
6392                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6393                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6394                                         switch(vid.renderpath)
6395                                         {
6396                                         case RENDERPATH_GL11:
6397                                         case RENDERPATH_GL13:
6398                                         case RENDERPATH_GL20:
6399                                         case RENDERPATH_GLES1:
6400                                         case RENDERPATH_GLES2:
6401                                         case RENDERPATH_SOFT:
6402                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6403                                                 break;
6404                                         case RENDERPATH_D3D9:
6405                                         case RENDERPATH_D3D10:
6406                                         case RENDERPATH_D3D11:
6407                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6408                                                 break;
6409                                         }
6410                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6411                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6412                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6413                                 }
6414                                 
6415                                 // updates old view angles for next pass 
6416                                 VectorCopy(cl.viewangles, blur_oldangles);
6417                         }
6418
6419                         // copy view into the screen texture
6420                         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);
6421                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6422                 }
6423                 else if (!r_bloomstate.texture_bloom)
6424                 {
6425                         // we may still have to do view tint...
6426                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6427                         {
6428                                 // apply a color tint to the whole view
6429                                 R_ResetViewRendering2D();
6430                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6431                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6432                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6433                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6434                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6435                         }
6436                         break; // no screen processing, no bloom, skip it
6437                 }
6438
6439                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6440                 {
6441                         // render simple bloom effect
6442                         // copy the screen and shrink it and darken it for the bloom process
6443                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6444                         // make the bloom texture
6445                         R_Bloom_MakeTexture();
6446                 }
6447
6448 #if _MSC_VER >= 1400
6449 #define sscanf sscanf_s
6450 #endif
6451                 memset(uservecs, 0, sizeof(uservecs));
6452                 if (r_glsl_postprocess_uservec1_enable.integer)
6453                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6454                 if (r_glsl_postprocess_uservec2_enable.integer)
6455                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6456                 if (r_glsl_postprocess_uservec3_enable.integer)
6457                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6458                 if (r_glsl_postprocess_uservec4_enable.integer)
6459                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6460
6461                 R_ResetViewRendering2D();
6462                 GL_Color(1, 1, 1, 1);
6463                 GL_BlendFunc(GL_ONE, GL_ZERO);
6464
6465                 switch(vid.renderpath)
6466                 {
6467                 case RENDERPATH_GL20:
6468                 case RENDERPATH_GLES2:
6469                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6470                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6471                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6472                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6473                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6474                         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]);
6475                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6476                         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]);
6477                         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]);
6478                         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]);
6479                         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]);
6480                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6481                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6482                         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);
6483                         break;
6484                 case RENDERPATH_D3D9:
6485 #ifdef SUPPORTD3D
6486                         // 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...
6487                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6488                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6489                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6490                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6491                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6492                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6493                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6494                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6495                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6496                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6497                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6498                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6499                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6500                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6501 #endif
6502                         break;
6503                 case RENDERPATH_D3D10:
6504                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6505                         break;
6506                 case RENDERPATH_D3D11:
6507                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6508                         break;
6509                 case RENDERPATH_SOFT:
6510                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6511                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6512                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6513                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6514                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6515                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6516                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6517                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6518                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6519                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6520                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6521                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6522                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6523                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6524                         break;
6525                 default:
6526                         break;
6527                 }
6528                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6529                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6530                 break;
6531         case RENDERPATH_GL11:
6532         case RENDERPATH_GL13:
6533         case RENDERPATH_GLES1:
6534                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6535                 {
6536                         // apply a color tint to the whole view
6537                         R_ResetViewRendering2D();
6538                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6539                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6540                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6541                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6542                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6543                 }
6544                 break;
6545         }
6546 }
6547
6548 matrix4x4_t r_waterscrollmatrix;
6549
6550 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6551 {
6552         // Nehahra fog
6553         if (gamemode == GAME_NEHAHRA)
6554         {
6555                 if (gl_fogenable.integer)
6556                 {
6557                         r_refdef.oldgl_fogenable = true;
6558                         r_refdef.fog_density = gl_fogdensity.value;
6559                         r_refdef.fog_red = gl_fogred.value;
6560                         r_refdef.fog_green = gl_foggreen.value;
6561                         r_refdef.fog_blue = gl_fogblue.value;
6562                         r_refdef.fog_alpha = 1;
6563                         r_refdef.fog_start = 0;
6564                         r_refdef.fog_end = gl_skyclip.value;
6565                         r_refdef.fog_height = 1<<30;
6566                         r_refdef.fog_fadedepth = 128;
6567                 }
6568                 else if (r_refdef.oldgl_fogenable)
6569                 {
6570                         r_refdef.oldgl_fogenable = false;
6571                         r_refdef.fog_density = 0;
6572                         r_refdef.fog_red = 0;
6573                         r_refdef.fog_green = 0;
6574                         r_refdef.fog_blue = 0;
6575                         r_refdef.fog_alpha = 0;
6576                         r_refdef.fog_start = 0;
6577                         r_refdef.fog_end = 0;
6578                         r_refdef.fog_height = 1<<30;
6579                         r_refdef.fog_fadedepth = 128;
6580                 }
6581         }
6582
6583         // fog parms
6584         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6585         r_refdef.fog_start = max(0, r_refdef.fog_start);
6586         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6587
6588         if (r_refdef.fog_density && r_drawfog.integer)
6589         {
6590                 r_refdef.fogenabled = true;
6591                 // this is the point where the fog reaches 0.9986 alpha, which we
6592                 // consider a good enough cutoff point for the texture
6593                 // (0.9986 * 256 == 255.6)
6594                 if (r_fog_exp2.integer)
6595                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6596                 else
6597                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6598                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6599                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6600                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6601                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6602                         R_BuildFogHeightTexture();
6603                 // fog color was already set
6604                 // update the fog texture
6605                 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)
6606                         R_BuildFogTexture();
6607                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6608                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6609         }
6610         else
6611                 r_refdef.fogenabled = false;
6612
6613         // fog color
6614         if (r_refdef.fog_density)
6615         {
6616                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6617                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6618                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6619
6620                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6621                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6622                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6623                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6624
6625                 {
6626                         vec3_t fogvec;
6627                         VectorCopy(r_refdef.fogcolor, fogvec);
6628                         //   color.rgb *= ContrastBoost * SceneBrightness;
6629                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6630                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6631                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6632                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6633                 }
6634         }
6635 }
6636
6637 void R_UpdateVariables(void)
6638 {
6639         R_Textures_Frame();
6640
6641         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6642
6643         r_refdef.farclip = r_farclip_base.value;
6644         if (r_refdef.scene.worldmodel)
6645                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6646         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6647
6648         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6649                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6650         r_refdef.polygonfactor = 0;
6651         r_refdef.polygonoffset = 0;
6652         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6653         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6654
6655         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6656         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6657         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6658         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6659         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6660         if (FAKELIGHT_ENABLED)
6661         {
6662                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6663         }
6664         if (r_showsurfaces.integer)
6665         {
6666                 r_refdef.scene.rtworld = false;
6667                 r_refdef.scene.rtworldshadows = false;
6668                 r_refdef.scene.rtdlight = false;
6669                 r_refdef.scene.rtdlightshadows = false;
6670                 r_refdef.lightmapintensity = 0;
6671         }
6672
6673         switch(vid.renderpath)
6674         {
6675         case RENDERPATH_GL20:
6676         case RENDERPATH_D3D9:
6677         case RENDERPATH_D3D10:
6678         case RENDERPATH_D3D11:
6679         case RENDERPATH_SOFT:
6680         case RENDERPATH_GLES2:
6681                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6682                 {
6683                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6684                         {
6685                                 // build GLSL gamma texture
6686 #define RAMPWIDTH 256
6687                                 unsigned short ramp[RAMPWIDTH * 3];
6688                                 unsigned char rampbgr[RAMPWIDTH][4];
6689                                 int i;
6690
6691                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6692
6693                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6694                                 for(i = 0; i < RAMPWIDTH; ++i)
6695                                 {
6696                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6697                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6698                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6699                                         rampbgr[i][3] = 0;
6700                                 }
6701                                 if (r_texture_gammaramps)
6702                                 {
6703                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6704                                 }
6705                                 else
6706                                 {
6707                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6708                                 }
6709                         }
6710                 }
6711                 else
6712                 {
6713                         // remove GLSL gamma texture
6714                 }
6715                 break;
6716         case RENDERPATH_GL11:
6717         case RENDERPATH_GL13:
6718         case RENDERPATH_GLES1:
6719                 break;
6720         }
6721 }
6722
6723 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6724 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6725 /*
6726 ================
6727 R_SelectScene
6728 ================
6729 */
6730 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6731         if( scenetype != r_currentscenetype ) {
6732                 // store the old scenetype
6733                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6734                 r_currentscenetype = scenetype;
6735                 // move in the new scene
6736                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6737         }
6738 }
6739
6740 /*
6741 ================
6742 R_GetScenePointer
6743 ================
6744 */
6745 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6746 {
6747         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6748         if( scenetype == r_currentscenetype ) {
6749                 return &r_refdef.scene;
6750         } else {
6751                 return &r_scenes_store[ scenetype ];
6752         }
6753 }
6754
6755 int R_SortEntities_Compare(const void *ap, const void *bp)
6756 {
6757         const entity_render_t *a = *(const entity_render_t **)ap;
6758         const entity_render_t *b = *(const entity_render_t **)bp;
6759
6760         // 1. compare model
6761         if(a->model < b->model)
6762                 return -1;
6763         if(a->model > b->model)
6764                 return +1;
6765
6766         // 2. compare skin
6767         // TODO possibly calculate the REAL skinnum here first using
6768         // skinscenes?
6769         if(a->skinnum < b->skinnum)
6770                 return -1;
6771         if(a->skinnum > b->skinnum)
6772                 return +1;
6773
6774         // everything we compared is equal
6775         return 0;
6776 }
6777 void R_SortEntities(void)
6778 {
6779         // below or equal 2 ents, sorting never gains anything
6780         if(r_refdef.scene.numentities <= 2)
6781                 return;
6782         // sort
6783         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6784 }
6785
6786 /*
6787 ================
6788 R_RenderView
6789 ================
6790 */
6791 int dpsoftrast_test;
6792 extern void R_Shadow_UpdateBounceGridTexture(void);
6793 extern cvar_t r_shadow_bouncegrid;
6794 void R_RenderView(void)
6795 {
6796         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6797
6798         dpsoftrast_test = r_test.integer;
6799
6800         if (r_timereport_active)
6801                 R_TimeReport("start");
6802         r_textureframe++; // used only by R_GetCurrentTexture
6803         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6804
6805         if(R_CompileShader_CheckStaticParms())
6806                 R_GLSL_Restart_f();
6807
6808         if (!r_drawentities.integer)
6809                 r_refdef.scene.numentities = 0;
6810         else if (r_sortentities.integer)
6811                 R_SortEntities();
6812
6813         R_AnimCache_ClearCache();
6814         R_FrameData_NewFrame();
6815
6816         /* adjust for stereo display */
6817         if(R_Stereo_Active())
6818         {
6819                 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);
6820                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6821         }
6822
6823         if (r_refdef.view.isoverlay)
6824         {
6825                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6826                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6827                 R_TimeReport("depthclear");
6828
6829                 r_refdef.view.showdebug = false;
6830
6831                 r_waterstate.enabled = false;
6832                 r_waterstate.numwaterplanes = 0;
6833
6834                 R_RenderScene();
6835
6836                 r_refdef.view.matrix = originalmatrix;
6837
6838                 CHECKGLERROR
6839                 return;
6840         }
6841
6842         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6843         {
6844                 r_refdef.view.matrix = originalmatrix;
6845                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6846         }
6847
6848         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6849
6850         R_RenderView_UpdateViewVectors();
6851
6852         R_Shadow_UpdateWorldLightSelection();
6853
6854         R_Bloom_StartFrame();
6855         R_Water_StartFrame();
6856
6857         CHECKGLERROR
6858         if (r_timereport_active)
6859                 R_TimeReport("viewsetup");
6860
6861         R_ResetViewRendering3D();
6862
6863         if (r_refdef.view.clear || r_refdef.fogenabled)
6864         {
6865                 R_ClearScreen(r_refdef.fogenabled);
6866                 if (r_timereport_active)
6867                         R_TimeReport("viewclear");
6868         }
6869         r_refdef.view.clear = true;
6870
6871         // this produces a bloom texture to be used in R_BlendView() later
6872         if (r_bloomstate.hdr)
6873         {
6874                 R_HDR_RenderBloomTexture();
6875                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6876                 r_textureframe++; // used only by R_GetCurrentTexture
6877         }
6878
6879         r_refdef.view.showdebug = true;
6880
6881         R_View_Update();
6882         if (r_timereport_active)
6883                 R_TimeReport("visibility");
6884
6885         R_Shadow_UpdateBounceGridTexture();
6886         if (r_timereport_active && r_shadow_bouncegrid.integer)
6887                 R_TimeReport("bouncegrid");
6888
6889         r_waterstate.numwaterplanes = 0;
6890         if (r_waterstate.enabled)
6891                 R_RenderWaterPlanes();
6892
6893         R_RenderScene();
6894         r_waterstate.numwaterplanes = 0;
6895
6896         R_BlendView();
6897         if (r_timereport_active)
6898                 R_TimeReport("blendview");
6899
6900         GL_Scissor(0, 0, vid.width, vid.height);
6901         GL_ScissorTest(false);
6902
6903         r_refdef.view.matrix = originalmatrix;
6904
6905         CHECKGLERROR
6906 }
6907
6908 void R_RenderWaterPlanes(void)
6909 {
6910         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6911         {
6912                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6913                 if (r_timereport_active)
6914                         R_TimeReport("waterworld");
6915         }
6916
6917         // don't let sound skip if going slow
6918         if (r_refdef.scene.extraupdate)
6919                 S_ExtraUpdate ();
6920
6921         R_DrawModelsAddWaterPlanes();
6922         if (r_timereport_active)
6923                 R_TimeReport("watermodels");
6924
6925         if (r_waterstate.numwaterplanes)
6926         {
6927                 R_Water_ProcessPlanes();
6928                 if (r_timereport_active)
6929                         R_TimeReport("waterscenes");
6930         }
6931 }
6932
6933 extern void R_DrawLightningBeams (void);
6934 extern void VM_CL_AddPolygonsToMeshQueue (void);
6935 extern void R_DrawPortals (void);
6936 extern cvar_t cl_locs_show;
6937 static void R_DrawLocs(void);
6938 static void R_DrawEntityBBoxes(void);
6939 static void R_DrawModelDecals(void);
6940 extern void R_DrawModelShadows(void);
6941 extern void R_DrawModelShadowMaps(void);
6942 extern cvar_t cl_decals_newsystem;
6943 extern qboolean r_shadow_usingdeferredprepass;
6944 void R_RenderScene(void)
6945 {
6946         qboolean shadowmapping = false;
6947
6948         if (r_timereport_active)
6949                 R_TimeReport("beginscene");
6950
6951         r_refdef.stats.renders++;
6952
6953         R_UpdateFog();
6954
6955         // don't let sound skip if going slow
6956         if (r_refdef.scene.extraupdate)
6957                 S_ExtraUpdate ();
6958
6959         R_MeshQueue_BeginScene();
6960
6961         R_SkyStartFrame();
6962
6963         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);
6964
6965         if (r_timereport_active)
6966                 R_TimeReport("skystartframe");
6967
6968         if (cl.csqc_vidvars.drawworld)
6969         {
6970                 // don't let sound skip if going slow
6971                 if (r_refdef.scene.extraupdate)
6972                         S_ExtraUpdate ();
6973
6974                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6975                 {
6976                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6977                         if (r_timereport_active)
6978                                 R_TimeReport("worldsky");
6979                 }
6980
6981                 if (R_DrawBrushModelsSky() && r_timereport_active)
6982                         R_TimeReport("bmodelsky");
6983
6984                 if (skyrendermasked && skyrenderlater)
6985                 {
6986                         // we have to force off the water clipping plane while rendering sky
6987                         R_SetupView(false);
6988                         R_Sky();
6989                         R_SetupView(true);
6990                         if (r_timereport_active)
6991                                 R_TimeReport("sky");
6992                 }
6993         }
6994
6995         R_AnimCache_CacheVisibleEntities();
6996         if (r_timereport_active)
6997                 R_TimeReport("animation");
6998
6999         R_Shadow_PrepareLights();
7000         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7001                 R_Shadow_PrepareModelShadows();
7002         if (r_timereport_active)
7003                 R_TimeReport("preparelights");
7004
7005         if (R_Shadow_ShadowMappingEnabled())
7006                 shadowmapping = true;
7007
7008         if (r_shadow_usingdeferredprepass)
7009                 R_Shadow_DrawPrepass();
7010
7011         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7012         {
7013                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7014                 if (r_timereport_active)
7015                         R_TimeReport("worlddepth");
7016         }
7017         if (r_depthfirst.integer >= 2)
7018         {
7019                 R_DrawModelsDepth();
7020                 if (r_timereport_active)
7021                         R_TimeReport("modeldepth");
7022         }
7023
7024         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7025         {
7026                 R_DrawModelShadowMaps();
7027                 R_ResetViewRendering3D();
7028                 // don't let sound skip if going slow
7029                 if (r_refdef.scene.extraupdate)
7030                         S_ExtraUpdate ();
7031         }
7032
7033         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7034         {
7035                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7036                 if (r_timereport_active)
7037                         R_TimeReport("world");
7038         }
7039
7040         // don't let sound skip if going slow
7041         if (r_refdef.scene.extraupdate)
7042                 S_ExtraUpdate ();
7043
7044         R_DrawModels();
7045         if (r_timereport_active)
7046                 R_TimeReport("models");
7047
7048         // don't let sound skip if going slow
7049         if (r_refdef.scene.extraupdate)
7050                 S_ExtraUpdate ();
7051
7052         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7053         {
7054                 R_DrawModelShadows();
7055                 R_ResetViewRendering3D();
7056                 // don't let sound skip if going slow
7057                 if (r_refdef.scene.extraupdate)
7058                         S_ExtraUpdate ();
7059         }
7060
7061         if (!r_shadow_usingdeferredprepass)
7062         {
7063                 R_Shadow_DrawLights();
7064                 if (r_timereport_active)
7065                         R_TimeReport("rtlights");
7066         }
7067
7068         // don't let sound skip if going slow
7069         if (r_refdef.scene.extraupdate)
7070                 S_ExtraUpdate ();
7071
7072         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7073         {
7074                 R_DrawModelShadows();
7075                 R_ResetViewRendering3D();
7076                 // don't let sound skip if going slow
7077                 if (r_refdef.scene.extraupdate)
7078                         S_ExtraUpdate ();
7079         }
7080
7081         if (cl.csqc_vidvars.drawworld)
7082         {
7083                 if (cl_decals_newsystem.integer)
7084                 {
7085                         R_DrawModelDecals();
7086                         if (r_timereport_active)
7087                                 R_TimeReport("modeldecals");
7088                 }
7089                 else
7090                 {
7091                         R_DrawDecals();
7092                         if (r_timereport_active)
7093                                 R_TimeReport("decals");
7094                 }
7095
7096                 R_DrawParticles();
7097                 if (r_timereport_active)
7098                         R_TimeReport("particles");
7099
7100                 R_DrawExplosions();
7101                 if (r_timereport_active)
7102                         R_TimeReport("explosions");
7103
7104                 R_DrawLightningBeams();
7105                 if (r_timereport_active)
7106                         R_TimeReport("lightning");
7107         }
7108
7109         VM_CL_AddPolygonsToMeshQueue();
7110
7111         if (r_refdef.view.showdebug)
7112         {
7113                 if (cl_locs_show.integer)
7114                 {
7115                         R_DrawLocs();
7116                         if (r_timereport_active)
7117                                 R_TimeReport("showlocs");
7118                 }
7119
7120                 if (r_drawportals.integer)
7121                 {
7122                         R_DrawPortals();
7123                         if (r_timereport_active)
7124                                 R_TimeReport("portals");
7125                 }
7126
7127                 if (r_showbboxes.value > 0)
7128                 {
7129                         R_DrawEntityBBoxes();
7130                         if (r_timereport_active)
7131                                 R_TimeReport("bboxes");
7132                 }
7133         }
7134
7135         if (r_transparent.integer)
7136         {
7137                 R_MeshQueue_RenderTransparent();
7138                 if (r_timereport_active)
7139                         R_TimeReport("drawtrans");
7140         }
7141
7142         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))
7143         {
7144                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7145                 if (r_timereport_active)
7146                         R_TimeReport("worlddebug");
7147                 R_DrawModelsDebug();
7148                 if (r_timereport_active)
7149                         R_TimeReport("modeldebug");
7150         }
7151
7152         if (cl.csqc_vidvars.drawworld)
7153         {
7154                 R_Shadow_DrawCoronas();
7155                 if (r_timereport_active)
7156                         R_TimeReport("coronas");
7157         }
7158
7159 #if 0
7160         {
7161                 GL_DepthTest(false);
7162                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7163                 GL_Color(1, 1, 1, 1);
7164                 qglBegin(GL_POLYGON);
7165                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7166                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7167                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7168                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7169                 qglEnd();
7170                 qglBegin(GL_POLYGON);
7171                 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]);
7172                 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]);
7173                 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]);
7174                 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]);
7175                 qglEnd();
7176                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7177         }
7178 #endif
7179
7180         // don't let sound skip if going slow
7181         if (r_refdef.scene.extraupdate)
7182                 S_ExtraUpdate ();
7183
7184         R_ResetViewRendering2D();
7185 }
7186
7187 static const unsigned short bboxelements[36] =
7188 {
7189         5, 1, 3, 5, 3, 7,
7190         6, 2, 0, 6, 0, 4,
7191         7, 3, 2, 7, 2, 6,
7192         4, 0, 1, 4, 1, 5,
7193         4, 5, 7, 4, 7, 6,
7194         1, 0, 2, 1, 2, 3,
7195 };
7196
7197 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7198 {
7199         int i;
7200         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7201
7202         RSurf_ActiveWorldEntity();
7203
7204         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7205         GL_DepthMask(false);
7206         GL_DepthRange(0, 1);
7207         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7208 //      R_Mesh_ResetTextureState();
7209
7210         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7211         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7212         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7213         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7214         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7215         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7216         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7217         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7218         R_FillColors(color4f, 8, cr, cg, cb, ca);
7219         if (r_refdef.fogenabled)
7220         {
7221                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7222                 {
7223                         f1 = RSurf_FogVertex(v);
7224                         f2 = 1 - f1;
7225                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7226                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7227                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7228                 }
7229         }
7230         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7231         R_Mesh_ResetTextureState();
7232         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7233         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7234 }
7235
7236 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7237 {
7238         int i;
7239         float color[4];
7240         prvm_edict_t *edict;
7241         prvm_prog_t *prog_save = prog;
7242
7243         // this function draws bounding boxes of server entities
7244         if (!sv.active)
7245                 return;
7246
7247         GL_CullFace(GL_NONE);
7248         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7249
7250         prog = 0;
7251         SV_VM_Begin();
7252         for (i = 0;i < numsurfaces;i++)
7253         {
7254                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7255                 switch ((int)PRVM_serveredictfloat(edict, solid))
7256                 {
7257                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7258                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7259                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7260                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7261                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7262                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7263                 }
7264                 color[3] *= r_showbboxes.value;
7265                 color[3] = bound(0, color[3], 1);
7266                 GL_DepthTest(!r_showdisabledepthtest.integer);
7267                 GL_CullFace(r_refdef.view.cullface_front);
7268                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7269         }
7270         SV_VM_End();
7271         prog = prog_save;
7272 }
7273
7274 static void R_DrawEntityBBoxes(void)
7275 {
7276         int i;
7277         prvm_edict_t *edict;
7278         vec3_t center;
7279         prvm_prog_t *prog_save = prog;
7280
7281         // this function draws bounding boxes of server entities
7282         if (!sv.active)
7283                 return;
7284
7285         prog = 0;
7286         SV_VM_Begin();
7287         for (i = 0;i < prog->num_edicts;i++)
7288         {
7289                 edict = PRVM_EDICT_NUM(i);
7290                 if (edict->priv.server->free)
7291                         continue;
7292                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7293                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7294                         continue;
7295                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7296                         continue;
7297                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7298                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7299         }
7300         SV_VM_End();
7301         prog = prog_save;
7302 }
7303
7304 static const int nomodelelement3i[24] =
7305 {
7306         5, 2, 0,
7307         5, 1, 2,
7308         5, 0, 3,
7309         5, 3, 1,
7310         0, 2, 4,
7311         2, 1, 4,
7312         3, 0, 4,
7313         1, 3, 4
7314 };
7315
7316 static const unsigned short nomodelelement3s[24] =
7317 {
7318         5, 2, 0,
7319         5, 1, 2,
7320         5, 0, 3,
7321         5, 3, 1,
7322         0, 2, 4,
7323         2, 1, 4,
7324         3, 0, 4,
7325         1, 3, 4
7326 };
7327
7328 static const float nomodelvertex3f[6*3] =
7329 {
7330         -16,   0,   0,
7331          16,   0,   0,
7332           0, -16,   0,
7333           0,  16,   0,
7334           0,   0, -16,
7335           0,   0,  16
7336 };
7337
7338 static const float nomodelcolor4f[6*4] =
7339 {
7340         0.0f, 0.0f, 0.5f, 1.0f,
7341         0.0f, 0.0f, 0.5f, 1.0f,
7342         0.0f, 0.5f, 0.0f, 1.0f,
7343         0.0f, 0.5f, 0.0f, 1.0f,
7344         0.5f, 0.0f, 0.0f, 1.0f,
7345         0.5f, 0.0f, 0.0f, 1.0f
7346 };
7347
7348 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7349 {
7350         int i;
7351         float f1, f2, *c;
7352         float color4f[6*4];
7353
7354         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);
7355
7356         // this is only called once per entity so numsurfaces is always 1, and
7357         // surfacelist is always {0}, so this code does not handle batches
7358
7359         if (rsurface.ent_flags & RENDER_ADDITIVE)
7360         {
7361                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7362                 GL_DepthMask(false);
7363         }
7364         else if (rsurface.colormod[3] < 1)
7365         {
7366                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7367                 GL_DepthMask(false);
7368         }
7369         else
7370         {
7371                 GL_BlendFunc(GL_ONE, GL_ZERO);
7372                 GL_DepthMask(true);
7373         }
7374         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7375         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7376         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7377         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7378         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7379         for (i = 0, c = color4f;i < 6;i++, c += 4)
7380         {
7381                 c[0] *= rsurface.colormod[0];
7382                 c[1] *= rsurface.colormod[1];
7383                 c[2] *= rsurface.colormod[2];
7384                 c[3] *= rsurface.colormod[3];
7385         }
7386         if (r_refdef.fogenabled)
7387         {
7388                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7389                 {
7390                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7391                         f2 = 1 - f1;
7392                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7393                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7394                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7395                 }
7396         }
7397 //      R_Mesh_ResetTextureState();
7398         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7399         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7400         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7401 }
7402
7403 void R_DrawNoModel(entity_render_t *ent)
7404 {
7405         vec3_t org;
7406         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7407         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7408                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7409         else
7410                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7411 }
7412
7413 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7414 {
7415         vec3_t right1, right2, diff, normal;
7416
7417         VectorSubtract (org2, org1, normal);
7418
7419         // calculate 'right' vector for start
7420         VectorSubtract (r_refdef.view.origin, org1, diff);
7421         CrossProduct (normal, diff, right1);
7422         VectorNormalize (right1);
7423
7424         // calculate 'right' vector for end
7425         VectorSubtract (r_refdef.view.origin, org2, diff);
7426         CrossProduct (normal, diff, right2);
7427         VectorNormalize (right2);
7428
7429         vert[ 0] = org1[0] + width * right1[0];
7430         vert[ 1] = org1[1] + width * right1[1];
7431         vert[ 2] = org1[2] + width * right1[2];
7432         vert[ 3] = org1[0] - width * right1[0];
7433         vert[ 4] = org1[1] - width * right1[1];
7434         vert[ 5] = org1[2] - width * right1[2];
7435         vert[ 6] = org2[0] - width * right2[0];
7436         vert[ 7] = org2[1] - width * right2[1];
7437         vert[ 8] = org2[2] - width * right2[2];
7438         vert[ 9] = org2[0] + width * right2[0];
7439         vert[10] = org2[1] + width * right2[1];
7440         vert[11] = org2[2] + width * right2[2];
7441 }
7442
7443 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)
7444 {
7445         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7446         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7447         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7448         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7449         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7450         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7451         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7452         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7453         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7454         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7455         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7456         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7457 }
7458
7459 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7460 {
7461         int i;
7462         float *vertex3f;
7463         float v[3];
7464         VectorSet(v, x, y, z);
7465         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7466                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7467                         break;
7468         if (i == mesh->numvertices)
7469         {
7470                 if (mesh->numvertices < mesh->maxvertices)
7471                 {
7472                         VectorCopy(v, vertex3f);
7473                         mesh->numvertices++;
7474                 }
7475                 return mesh->numvertices;
7476         }
7477         else
7478                 return i;
7479 }
7480
7481 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7482 {
7483         int i;
7484         int *e, element[3];
7485         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7486         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7487         e = mesh->element3i + mesh->numtriangles * 3;
7488         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7489         {
7490                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7491                 if (mesh->numtriangles < mesh->maxtriangles)
7492                 {
7493                         *e++ = element[0];
7494                         *e++ = element[1];
7495                         *e++ = element[2];
7496                         mesh->numtriangles++;
7497                 }
7498                 element[1] = element[2];
7499         }
7500 }
7501
7502 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7503 {
7504         int i;
7505         int *e, element[3];
7506         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7507         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7508         e = mesh->element3i + mesh->numtriangles * 3;
7509         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7510         {
7511                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7512                 if (mesh->numtriangles < mesh->maxtriangles)
7513                 {
7514                         *e++ = element[0];
7515                         *e++ = element[1];
7516                         *e++ = element[2];
7517                         mesh->numtriangles++;
7518                 }
7519                 element[1] = element[2];
7520         }
7521 }
7522
7523 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7524 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7525 {
7526         int planenum, planenum2;
7527         int w;
7528         int tempnumpoints;
7529         mplane_t *plane, *plane2;
7530         double maxdist;
7531         double temppoints[2][256*3];
7532         // figure out how large a bounding box we need to properly compute this brush
7533         maxdist = 0;
7534         for (w = 0;w < numplanes;w++)
7535                 maxdist = max(maxdist, fabs(planes[w].dist));
7536         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7537         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7538         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7539         {
7540                 w = 0;
7541                 tempnumpoints = 4;
7542                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7543                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7544                 {
7545                         if (planenum2 == planenum)
7546                                 continue;
7547                         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);
7548                         w = !w;
7549                 }
7550                 if (tempnumpoints < 3)
7551                         continue;
7552                 // generate elements forming a triangle fan for this polygon
7553                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7554         }
7555 }
7556
7557 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)
7558 {
7559         texturelayer_t *layer;
7560         layer = t->currentlayers + t->currentnumlayers++;
7561         layer->type = type;
7562         layer->depthmask = depthmask;
7563         layer->blendfunc1 = blendfunc1;
7564         layer->blendfunc2 = blendfunc2;
7565         layer->texture = texture;
7566         layer->texmatrix = *matrix;
7567         layer->color[0] = r;
7568         layer->color[1] = g;
7569         layer->color[2] = b;
7570         layer->color[3] = a;
7571 }
7572
7573 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7574 {
7575         if(parms[0] == 0 && parms[1] == 0)
7576                 return false;
7577         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7578                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7579                         return false;
7580         return true;
7581 }
7582
7583 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7584 {
7585         double index, f;
7586         index = parms[2] + rsurface.shadertime * parms[3];
7587         index -= floor(index);
7588         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7589         {
7590         default:
7591         case Q3WAVEFUNC_NONE:
7592         case Q3WAVEFUNC_NOISE:
7593         case Q3WAVEFUNC_COUNT:
7594                 f = 0;
7595                 break;
7596         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7597         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7598         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7599         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7600         case Q3WAVEFUNC_TRIANGLE:
7601                 index *= 4;
7602                 f = index - floor(index);
7603                 if (index < 1)
7604                 {
7605                         // f = f;
7606                 }
7607                 else if (index < 2)
7608                         f = 1 - f;
7609                 else if (index < 3)
7610                         f = -f;
7611                 else
7612                         f = -(1 - f);
7613                 break;
7614         }
7615         f = parms[0] + parms[1] * f;
7616         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7617                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7618         return (float) f;
7619 }
7620
7621 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7622 {
7623         int w, h, idx;
7624         double f;
7625         double offsetd[2];
7626         float tcmat[12];
7627         matrix4x4_t matrix, temp;
7628         switch(tcmod->tcmod)
7629         {
7630                 case Q3TCMOD_COUNT:
7631                 case Q3TCMOD_NONE:
7632                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7633                                 matrix = r_waterscrollmatrix;
7634                         else
7635                                 matrix = identitymatrix;
7636                         break;
7637                 case Q3TCMOD_ENTITYTRANSLATE:
7638                         // this is used in Q3 to allow the gamecode to control texcoord
7639                         // scrolling on the entity, which is not supported in darkplaces yet.
7640                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7641                         break;
7642                 case Q3TCMOD_ROTATE:
7643                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7644                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7645                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7646                         break;
7647                 case Q3TCMOD_SCALE:
7648                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7649                         break;
7650                 case Q3TCMOD_SCROLL:
7651                         // extra care is needed because of precision breakdown with large values of time
7652                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7653                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7654                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7655                         break;
7656                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7657                         w = (int) tcmod->parms[0];
7658                         h = (int) tcmod->parms[1];
7659                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7660                         f = f - floor(f);
7661                         idx = (int) floor(f * w * h);
7662                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7663                         break;
7664                 case Q3TCMOD_STRETCH:
7665                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7666                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7667                         break;
7668                 case Q3TCMOD_TRANSFORM:
7669                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7670                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7671                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7672                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7673                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7674                         break;
7675                 case Q3TCMOD_TURBULENT:
7676                         // this is handled in the RSurf_PrepareVertices function
7677                         matrix = identitymatrix;
7678                         break;
7679         }
7680         temp = *texmatrix;
7681         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7682 }
7683
7684 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7685 {
7686         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7687         char name[MAX_QPATH];
7688         skinframe_t *skinframe;
7689         unsigned char pixels[296*194];
7690         strlcpy(cache->name, skinname, sizeof(cache->name));
7691         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7692         if (developer_loading.integer)
7693                 Con_Printf("loading %s\n", name);
7694         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7695         if (!skinframe || !skinframe->base)
7696         {
7697                 unsigned char *f;
7698                 fs_offset_t filesize;
7699                 skinframe = NULL;
7700                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7701                 if (f)
7702                 {
7703                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7704                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7705                         Mem_Free(f);
7706                 }
7707         }
7708         cache->skinframe = skinframe;
7709 }
7710
7711 texture_t *R_GetCurrentTexture(texture_t *t)
7712 {
7713         int i;
7714         const entity_render_t *ent = rsurface.entity;
7715         dp_model_t *model = ent->model;
7716         q3shaderinfo_layer_tcmod_t *tcmod;
7717
7718         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7719                 return t->currentframe;
7720         t->update_lastrenderframe = r_textureframe;
7721         t->update_lastrenderentity = (void *)ent;
7722
7723         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7724                 t->camera_entity = ent->entitynumber;
7725         else
7726                 t->camera_entity = 0;
7727
7728         // switch to an alternate material if this is a q1bsp animated material
7729         {
7730                 texture_t *texture = t;
7731                 int s = rsurface.ent_skinnum;
7732                 if ((unsigned int)s >= (unsigned int)model->numskins)
7733                         s = 0;
7734                 if (model->skinscenes)
7735                 {
7736                         if (model->skinscenes[s].framecount > 1)
7737                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7738                         else
7739                                 s = model->skinscenes[s].firstframe;
7740                 }
7741                 if (s > 0)
7742                         t = t + s * model->num_surfaces;
7743                 if (t->animated)
7744                 {
7745                         // use an alternate animation if the entity's frame is not 0,
7746                         // and only if the texture has an alternate animation
7747                         if (rsurface.ent_alttextures && t->anim_total[1])
7748                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7749                         else
7750                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7751                 }
7752                 texture->currentframe = t;
7753         }
7754
7755         // update currentskinframe to be a qw skin or animation frame
7756         if (rsurface.ent_qwskin >= 0)
7757         {
7758                 i = rsurface.ent_qwskin;
7759                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7760                 {
7761                         r_qwskincache_size = cl.maxclients;
7762                         if (r_qwskincache)
7763                                 Mem_Free(r_qwskincache);
7764                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7765                 }
7766                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7767                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7768                 t->currentskinframe = r_qwskincache[i].skinframe;
7769                 if (t->currentskinframe == NULL)
7770                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7771         }
7772         else if (t->numskinframes >= 2)
7773                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7774         if (t->backgroundnumskinframes >= 2)
7775                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7776
7777         t->currentmaterialflags = t->basematerialflags;
7778         t->currentalpha = rsurface.colormod[3];
7779         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7780                 t->currentalpha *= r_wateralpha.value;
7781         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7782                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7783         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7784                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7785         if (!(rsurface.ent_flags & RENDER_LIGHT))
7786                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7787         else if (FAKELIGHT_ENABLED)
7788         {
7789                 // no modellight if using fakelight for the map
7790         }
7791         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7792         {
7793                 // pick a model lighting mode
7794                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7795                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7796                 else
7797                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7798         }
7799         if (rsurface.ent_flags & RENDER_ADDITIVE)
7800                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7801         else if (t->currentalpha < 1)
7802                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7803         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7804                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7805         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7806                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7807         if (t->backgroundnumskinframes)
7808                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7809         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7810         {
7811                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7812                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7813         }
7814         else
7815                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7816         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7817         {
7818                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7819                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7820         }
7821         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7822                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7823
7824         // there is no tcmod
7825         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7826         {
7827                 t->currenttexmatrix = r_waterscrollmatrix;
7828                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7829         }
7830         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7831         {
7832                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7833                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7834         }
7835
7836         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7837                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7838         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7839                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7840
7841         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7842         if (t->currentskinframe->qpixels)
7843                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7844         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7845         if (!t->basetexture)
7846                 t->basetexture = r_texture_notexture;
7847         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7848         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7849         t->nmaptexture = t->currentskinframe->nmap;
7850         if (!t->nmaptexture)
7851                 t->nmaptexture = r_texture_blanknormalmap;
7852         t->glosstexture = r_texture_black;
7853         t->glowtexture = t->currentskinframe->glow;
7854         t->fogtexture = t->currentskinframe->fog;
7855         t->reflectmasktexture = t->currentskinframe->reflect;
7856         if (t->backgroundnumskinframes)
7857         {
7858                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7859                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7860                 t->backgroundglosstexture = r_texture_black;
7861                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7862                 if (!t->backgroundnmaptexture)
7863                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7864         }
7865         else
7866         {
7867                 t->backgroundbasetexture = r_texture_white;
7868                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7869                 t->backgroundglosstexture = r_texture_black;
7870                 t->backgroundglowtexture = NULL;
7871         }
7872         t->specularpower = r_shadow_glossexponent.value;
7873         // TODO: store reference values for these in the texture?
7874         t->specularscale = 0;
7875         if (r_shadow_gloss.integer > 0)
7876         {
7877                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7878                 {
7879                         if (r_shadow_glossintensity.value > 0)
7880                         {
7881                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7882                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7883                                 t->specularscale = r_shadow_glossintensity.value;
7884                         }
7885                 }
7886                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7887                 {
7888                         t->glosstexture = r_texture_white;
7889                         t->backgroundglosstexture = r_texture_white;
7890                         t->specularscale = r_shadow_gloss2intensity.value;
7891                         t->specularpower = r_shadow_gloss2exponent.value;
7892                 }
7893         }
7894         t->specularscale *= t->specularscalemod;
7895         t->specularpower *= t->specularpowermod;
7896
7897         // lightmaps mode looks bad with dlights using actual texturing, so turn
7898         // off the colormap and glossmap, but leave the normalmap on as it still
7899         // accurately represents the shading involved
7900         if (gl_lightmaps.integer)
7901         {
7902                 t->basetexture = r_texture_grey128;
7903                 t->pantstexture = r_texture_black;
7904                 t->shirttexture = r_texture_black;
7905                 t->nmaptexture = r_texture_blanknormalmap;
7906                 t->glosstexture = r_texture_black;
7907                 t->glowtexture = NULL;
7908                 t->fogtexture = NULL;
7909                 t->reflectmasktexture = NULL;
7910                 t->backgroundbasetexture = NULL;
7911                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7912                 t->backgroundglosstexture = r_texture_black;
7913                 t->backgroundglowtexture = NULL;
7914                 t->specularscale = 0;
7915                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7916         }
7917
7918         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7919         VectorClear(t->dlightcolor);
7920         t->currentnumlayers = 0;
7921         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7922         {
7923                 int blendfunc1, blendfunc2;
7924                 qboolean depthmask;
7925                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7926                 {
7927                         blendfunc1 = GL_SRC_ALPHA;
7928                         blendfunc2 = GL_ONE;
7929                 }
7930                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7931                 {
7932                         blendfunc1 = GL_SRC_ALPHA;
7933                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7934                 }
7935                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7936                 {
7937                         blendfunc1 = t->customblendfunc[0];
7938                         blendfunc2 = t->customblendfunc[1];
7939                 }
7940                 else
7941                 {
7942                         blendfunc1 = GL_ONE;
7943                         blendfunc2 = GL_ZERO;
7944                 }
7945                 // don't colormod evilblend textures
7946                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7947                         VectorSet(t->lightmapcolor, 1, 1, 1);
7948                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7949                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7950                 {
7951                         // fullbright is not affected by r_refdef.lightmapintensity
7952                         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]);
7953                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7954                                 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]);
7955                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7956                                 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]);
7957                 }
7958                 else
7959                 {
7960                         vec3_t ambientcolor;
7961                         float colorscale;
7962                         // set the color tint used for lights affecting this surface
7963                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7964                         colorscale = 2;
7965                         // q3bsp has no lightmap updates, so the lightstylevalue that
7966                         // would normally be baked into the lightmap must be
7967                         // applied to the color
7968                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7969                         if (model->type == mod_brushq3)
7970                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7971                         colorscale *= r_refdef.lightmapintensity;
7972                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7973                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7974                         // basic lit geometry
7975                         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]);
7976                         // add pants/shirt if needed
7977                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7978                                 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]);
7979                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7980                                 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]);
7981                         // now add ambient passes if needed
7982                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7983                         {
7984                                 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]);
7985                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7986                                         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]);
7987                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7988                                         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]);
7989                         }
7990                 }
7991                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7992                         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]);
7993                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7994                 {
7995                         // if this is opaque use alpha blend which will darken the earlier
7996                         // passes cheaply.
7997                         //
7998                         // if this is an alpha blended material, all the earlier passes
7999                         // were darkened by fog already, so we only need to add the fog
8000                         // color ontop through the fog mask texture
8001                         //
8002                         // if this is an additive blended material, all the earlier passes
8003                         // were darkened by fog already, and we should not add fog color
8004                         // (because the background was not darkened, there is no fog color
8005                         // that was lost behind it).
8006                         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]);
8007                 }
8008         }
8009
8010         return t->currentframe;
8011 }
8012
8013 rsurfacestate_t rsurface;
8014
8015 void RSurf_ActiveWorldEntity(void)
8016 {
8017         dp_model_t *model = r_refdef.scene.worldmodel;
8018         //if (rsurface.entity == r_refdef.scene.worldentity)
8019         //      return;
8020         rsurface.entity = r_refdef.scene.worldentity;
8021         rsurface.skeleton = NULL;
8022         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8023         rsurface.ent_skinnum = 0;
8024         rsurface.ent_qwskin = -1;
8025         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8026         rsurface.shadertime = r_refdef.scene.time;
8027         rsurface.matrix = identitymatrix;
8028         rsurface.inversematrix = identitymatrix;
8029         rsurface.matrixscale = 1;
8030         rsurface.inversematrixscale = 1;
8031         R_EntityMatrix(&identitymatrix);
8032         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8033         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8034         rsurface.fograngerecip = r_refdef.fograngerecip;
8035         rsurface.fogheightfade = r_refdef.fogheightfade;
8036         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8037         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8038         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8039         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8040         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8041         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8042         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8043         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8044         rsurface.colormod[3] = 1;
8045         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);
8046         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8047         rsurface.frameblend[0].lerp = 1;
8048         rsurface.ent_alttextures = false;
8049         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8050         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8051         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8052         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8053         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8054         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8055         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8056         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8057         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8058         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8059         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8060         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8061         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8062         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8063         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8064         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8065         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8066         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8067         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8068         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8069         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8070         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8071         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8072         rsurface.modelelement3i = model->surfmesh.data_element3i;
8073         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8074         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8075         rsurface.modelelement3s = model->surfmesh.data_element3s;
8076         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8077         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8078         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8079         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8080         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8081         rsurface.modelsurfaces = model->data_surfaces;
8082         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8083         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8084         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8085         rsurface.modelgeneratedvertex = false;
8086         rsurface.batchgeneratedvertex = false;
8087         rsurface.batchfirstvertex = 0;
8088         rsurface.batchnumvertices = 0;
8089         rsurface.batchfirsttriangle = 0;
8090         rsurface.batchnumtriangles = 0;
8091         rsurface.batchvertex3f  = NULL;
8092         rsurface.batchvertex3f_vertexbuffer = NULL;
8093         rsurface.batchvertex3f_bufferoffset = 0;
8094         rsurface.batchsvector3f = NULL;
8095         rsurface.batchsvector3f_vertexbuffer = NULL;
8096         rsurface.batchsvector3f_bufferoffset = 0;
8097         rsurface.batchtvector3f = NULL;
8098         rsurface.batchtvector3f_vertexbuffer = NULL;
8099         rsurface.batchtvector3f_bufferoffset = 0;
8100         rsurface.batchnormal3f  = NULL;
8101         rsurface.batchnormal3f_vertexbuffer = NULL;
8102         rsurface.batchnormal3f_bufferoffset = 0;
8103         rsurface.batchlightmapcolor4f = NULL;
8104         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8105         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8106         rsurface.batchtexcoordtexture2f = NULL;
8107         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8108         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8109         rsurface.batchtexcoordlightmap2f = NULL;
8110         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8111         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8112         rsurface.batchvertexmesh = NULL;
8113         rsurface.batchvertexmeshbuffer = NULL;
8114         rsurface.batchvertex3fbuffer = NULL;
8115         rsurface.batchelement3i = NULL;
8116         rsurface.batchelement3i_indexbuffer = NULL;
8117         rsurface.batchelement3i_bufferoffset = 0;
8118         rsurface.batchelement3s = NULL;
8119         rsurface.batchelement3s_indexbuffer = NULL;
8120         rsurface.batchelement3s_bufferoffset = 0;
8121         rsurface.passcolor4f = NULL;
8122         rsurface.passcolor4f_vertexbuffer = NULL;
8123         rsurface.passcolor4f_bufferoffset = 0;
8124 }
8125
8126 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8127 {
8128         dp_model_t *model = ent->model;
8129         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8130         //      return;
8131         rsurface.entity = (entity_render_t *)ent;
8132         rsurface.skeleton = ent->skeleton;
8133         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8134         rsurface.ent_skinnum = ent->skinnum;
8135         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;
8136         rsurface.ent_flags = ent->flags;
8137         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8138         rsurface.matrix = ent->matrix;
8139         rsurface.inversematrix = ent->inversematrix;
8140         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8141         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8142         R_EntityMatrix(&rsurface.matrix);
8143         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8144         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8145         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8146         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8147         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8148         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8149         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8150         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8151         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8152         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8153         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8154         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8155         rsurface.colormod[3] = ent->alpha;
8156         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8157         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8158         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8159         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8160         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8161         if (ent->model->brush.submodel && !prepass)
8162         {
8163                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8164                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8165         }
8166         if (model->surfmesh.isanimated && model->AnimateVertices)
8167         {
8168                 if (ent->animcache_vertex3f)
8169                 {
8170                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8171                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8172                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8173                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8174                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8175                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8176                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8177                 }
8178                 else if (wanttangents)
8179                 {
8180                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8181                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8183                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8185                         rsurface.modelvertexmesh = NULL;
8186                         rsurface.modelvertexmeshbuffer = NULL;
8187                         rsurface.modelvertex3fbuffer = NULL;
8188                 }
8189                 else if (wantnormals)
8190                 {
8191                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8192                         rsurface.modelsvector3f = NULL;
8193                         rsurface.modeltvector3f = NULL;
8194                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8196                         rsurface.modelvertexmesh = NULL;
8197                         rsurface.modelvertexmeshbuffer = NULL;
8198                         rsurface.modelvertex3fbuffer = NULL;
8199                 }
8200                 else
8201                 {
8202                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8203                         rsurface.modelsvector3f = NULL;
8204                         rsurface.modeltvector3f = NULL;
8205                         rsurface.modelnormal3f = NULL;
8206                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8207                         rsurface.modelvertexmesh = NULL;
8208                         rsurface.modelvertexmeshbuffer = NULL;
8209                         rsurface.modelvertex3fbuffer = NULL;
8210                 }
8211                 rsurface.modelvertex3f_vertexbuffer = 0;
8212                 rsurface.modelvertex3f_bufferoffset = 0;
8213                 rsurface.modelsvector3f_vertexbuffer = 0;
8214                 rsurface.modelsvector3f_bufferoffset = 0;
8215                 rsurface.modeltvector3f_vertexbuffer = 0;
8216                 rsurface.modeltvector3f_bufferoffset = 0;
8217                 rsurface.modelnormal3f_vertexbuffer = 0;
8218                 rsurface.modelnormal3f_bufferoffset = 0;
8219                 rsurface.modelgeneratedvertex = true;
8220         }
8221         else
8222         {
8223                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8224                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8225                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8226                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8227                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8228                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8229                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8230                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8231                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8232                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8233                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8234                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8235                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8236                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8237                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8238                 rsurface.modelgeneratedvertex = false;
8239         }
8240         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8241         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8242         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8243         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8244         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8245         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8246         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8247         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8248         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8249         rsurface.modelelement3i = model->surfmesh.data_element3i;
8250         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8251         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8252         rsurface.modelelement3s = model->surfmesh.data_element3s;
8253         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8254         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8255         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8256         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8257         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8258         rsurface.modelsurfaces = model->data_surfaces;
8259         rsurface.batchgeneratedvertex = false;
8260         rsurface.batchfirstvertex = 0;
8261         rsurface.batchnumvertices = 0;
8262         rsurface.batchfirsttriangle = 0;
8263         rsurface.batchnumtriangles = 0;
8264         rsurface.batchvertex3f  = NULL;
8265         rsurface.batchvertex3f_vertexbuffer = NULL;
8266         rsurface.batchvertex3f_bufferoffset = 0;
8267         rsurface.batchsvector3f = NULL;
8268         rsurface.batchsvector3f_vertexbuffer = NULL;
8269         rsurface.batchsvector3f_bufferoffset = 0;
8270         rsurface.batchtvector3f = NULL;
8271         rsurface.batchtvector3f_vertexbuffer = NULL;
8272         rsurface.batchtvector3f_bufferoffset = 0;
8273         rsurface.batchnormal3f  = NULL;
8274         rsurface.batchnormal3f_vertexbuffer = NULL;
8275         rsurface.batchnormal3f_bufferoffset = 0;
8276         rsurface.batchlightmapcolor4f = NULL;
8277         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8278         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8279         rsurface.batchtexcoordtexture2f = NULL;
8280         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8281         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8282         rsurface.batchtexcoordlightmap2f = NULL;
8283         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8284         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8285         rsurface.batchvertexmesh = NULL;
8286         rsurface.batchvertexmeshbuffer = NULL;
8287         rsurface.batchvertex3fbuffer = NULL;
8288         rsurface.batchelement3i = NULL;
8289         rsurface.batchelement3i_indexbuffer = NULL;
8290         rsurface.batchelement3i_bufferoffset = 0;
8291         rsurface.batchelement3s = NULL;
8292         rsurface.batchelement3s_indexbuffer = NULL;
8293         rsurface.batchelement3s_bufferoffset = 0;
8294         rsurface.passcolor4f = NULL;
8295         rsurface.passcolor4f_vertexbuffer = NULL;
8296         rsurface.passcolor4f_bufferoffset = 0;
8297 }
8298
8299 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)
8300 {
8301         rsurface.entity = r_refdef.scene.worldentity;
8302         rsurface.skeleton = NULL;
8303         rsurface.ent_skinnum = 0;
8304         rsurface.ent_qwskin = -1;
8305         rsurface.ent_flags = entflags;
8306         rsurface.shadertime = r_refdef.scene.time - shadertime;
8307         rsurface.modelnumvertices = numvertices;
8308         rsurface.modelnumtriangles = numtriangles;
8309         rsurface.matrix = *matrix;
8310         rsurface.inversematrix = *inversematrix;
8311         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8312         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8313         R_EntityMatrix(&rsurface.matrix);
8314         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8315         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8316         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8317         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8318         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8319         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8320         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8321         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8322         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8323         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8324         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8325         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8326         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);
8327         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8328         rsurface.frameblend[0].lerp = 1;
8329         rsurface.ent_alttextures = false;
8330         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8331         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8332         if (wanttangents)
8333         {
8334                 rsurface.modelvertex3f = (float *)vertex3f;
8335                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8336                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8337                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8338         }
8339         else if (wantnormals)
8340         {
8341                 rsurface.modelvertex3f = (float *)vertex3f;
8342                 rsurface.modelsvector3f = NULL;
8343                 rsurface.modeltvector3f = NULL;
8344                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8345         }
8346         else
8347         {
8348                 rsurface.modelvertex3f = (float *)vertex3f;
8349                 rsurface.modelsvector3f = NULL;
8350                 rsurface.modeltvector3f = NULL;
8351                 rsurface.modelnormal3f = NULL;
8352         }
8353         rsurface.modelvertexmesh = NULL;
8354         rsurface.modelvertexmeshbuffer = NULL;
8355         rsurface.modelvertex3fbuffer = NULL;
8356         rsurface.modelvertex3f_vertexbuffer = 0;
8357         rsurface.modelvertex3f_bufferoffset = 0;
8358         rsurface.modelsvector3f_vertexbuffer = 0;
8359         rsurface.modelsvector3f_bufferoffset = 0;
8360         rsurface.modeltvector3f_vertexbuffer = 0;
8361         rsurface.modeltvector3f_bufferoffset = 0;
8362         rsurface.modelnormal3f_vertexbuffer = 0;
8363         rsurface.modelnormal3f_bufferoffset = 0;
8364         rsurface.modelgeneratedvertex = true;
8365         rsurface.modellightmapcolor4f  = (float *)color4f;
8366         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8367         rsurface.modellightmapcolor4f_bufferoffset = 0;
8368         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8369         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8370         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8371         rsurface.modeltexcoordlightmap2f  = NULL;
8372         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8373         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8374         rsurface.modelelement3i = (int *)element3i;
8375         rsurface.modelelement3i_indexbuffer = NULL;
8376         rsurface.modelelement3i_bufferoffset = 0;
8377         rsurface.modelelement3s = (unsigned short *)element3s;
8378         rsurface.modelelement3s_indexbuffer = NULL;
8379         rsurface.modelelement3s_bufferoffset = 0;
8380         rsurface.modellightmapoffsets = NULL;
8381         rsurface.modelsurfaces = NULL;
8382         rsurface.batchgeneratedvertex = false;
8383         rsurface.batchfirstvertex = 0;
8384         rsurface.batchnumvertices = 0;
8385         rsurface.batchfirsttriangle = 0;
8386         rsurface.batchnumtriangles = 0;
8387         rsurface.batchvertex3f  = NULL;
8388         rsurface.batchvertex3f_vertexbuffer = NULL;
8389         rsurface.batchvertex3f_bufferoffset = 0;
8390         rsurface.batchsvector3f = NULL;
8391         rsurface.batchsvector3f_vertexbuffer = NULL;
8392         rsurface.batchsvector3f_bufferoffset = 0;
8393         rsurface.batchtvector3f = NULL;
8394         rsurface.batchtvector3f_vertexbuffer = NULL;
8395         rsurface.batchtvector3f_bufferoffset = 0;
8396         rsurface.batchnormal3f  = NULL;
8397         rsurface.batchnormal3f_vertexbuffer = NULL;
8398         rsurface.batchnormal3f_bufferoffset = 0;
8399         rsurface.batchlightmapcolor4f = NULL;
8400         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8401         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8402         rsurface.batchtexcoordtexture2f = NULL;
8403         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8404         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8405         rsurface.batchtexcoordlightmap2f = NULL;
8406         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8407         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8408         rsurface.batchvertexmesh = NULL;
8409         rsurface.batchvertexmeshbuffer = NULL;
8410         rsurface.batchvertex3fbuffer = NULL;
8411         rsurface.batchelement3i = NULL;
8412         rsurface.batchelement3i_indexbuffer = NULL;
8413         rsurface.batchelement3i_bufferoffset = 0;
8414         rsurface.batchelement3s = NULL;
8415         rsurface.batchelement3s_indexbuffer = NULL;
8416         rsurface.batchelement3s_bufferoffset = 0;
8417         rsurface.passcolor4f = NULL;
8418         rsurface.passcolor4f_vertexbuffer = NULL;
8419         rsurface.passcolor4f_bufferoffset = 0;
8420
8421         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8422         {
8423                 if ((wantnormals || wanttangents) && !normal3f)
8424                 {
8425                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8426                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8427                 }
8428                 if (wanttangents && !svector3f)
8429                 {
8430                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8431                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8432                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8433                 }
8434         }
8435 }
8436
8437 float RSurf_FogPoint(const float *v)
8438 {
8439         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8440         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8441         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8442         float FogHeightFade = r_refdef.fogheightfade;
8443         float fogfrac;
8444         unsigned int fogmasktableindex;
8445         if (r_refdef.fogplaneviewabove)
8446                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8447         else
8448                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8449         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8450         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8451 }
8452
8453 float RSurf_FogVertex(const float *v)
8454 {
8455         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8456         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8457         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8458         float FogHeightFade = rsurface.fogheightfade;
8459         float fogfrac;
8460         unsigned int fogmasktableindex;
8461         if (r_refdef.fogplaneviewabove)
8462                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8463         else
8464                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8465         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8466         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8467 }
8468
8469 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8470 {
8471         int i;
8472         for (i = 0;i < numelements;i++)
8473                 outelement3i[i] = inelement3i[i] + adjust;
8474 }
8475
8476 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8477 extern cvar_t gl_vbo;
8478 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8479 {
8480         int deformindex;
8481         int firsttriangle;
8482         int numtriangles;
8483         int firstvertex;
8484         int endvertex;
8485         int numvertices;
8486         int surfacefirsttriangle;
8487         int surfacenumtriangles;
8488         int surfacefirstvertex;
8489         int surfaceendvertex;
8490         int surfacenumvertices;
8491         int batchnumvertices;
8492         int batchnumtriangles;
8493         int needsupdate;
8494         int i, j;
8495         qboolean gaps;
8496         qboolean dynamicvertex;
8497         float amplitude;
8498         float animpos;
8499         float scale;
8500         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8501         float waveparms[4];
8502         q3shaderinfo_deform_t *deform;
8503         const msurface_t *surface, *firstsurface;
8504         r_vertexmesh_t *vertexmesh;
8505         if (!texturenumsurfaces)
8506                 return;
8507         // find vertex range of this surface batch
8508         gaps = false;
8509         firstsurface = texturesurfacelist[0];
8510         firsttriangle = firstsurface->num_firsttriangle;
8511         batchnumvertices = 0;
8512         batchnumtriangles = 0;
8513         firstvertex = endvertex = firstsurface->num_firstvertex;
8514         for (i = 0;i < texturenumsurfaces;i++)
8515         {
8516                 surface = texturesurfacelist[i];
8517                 if (surface != firstsurface + i)
8518                         gaps = true;
8519                 surfacefirstvertex = surface->num_firstvertex;
8520                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8521                 surfacenumvertices = surface->num_vertices;
8522                 surfacenumtriangles = surface->num_triangles;
8523                 if (firstvertex > surfacefirstvertex)
8524                         firstvertex = surfacefirstvertex;
8525                 if (endvertex < surfaceendvertex)
8526                         endvertex = surfaceendvertex;
8527                 batchnumvertices += surfacenumvertices;
8528                 batchnumtriangles += surfacenumtriangles;
8529         }
8530
8531         // we now know the vertex range used, and if there are any gaps in it
8532         rsurface.batchfirstvertex = firstvertex;
8533         rsurface.batchnumvertices = endvertex - firstvertex;
8534         rsurface.batchfirsttriangle = firsttriangle;
8535         rsurface.batchnumtriangles = batchnumtriangles;
8536
8537         // this variable holds flags for which properties have been updated that
8538         // may require regenerating vertexmesh array...
8539         needsupdate = 0;
8540
8541         // check if any dynamic vertex processing must occur
8542         dynamicvertex = false;
8543
8544         // if there is a chance of animated vertex colors, it's a dynamic batch
8545         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8546         {
8547                 dynamicvertex = true;
8548                 batchneed |= BATCHNEED_NOGAPS;
8549                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8550         }
8551
8552         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8553         {
8554                 switch (deform->deform)
8555                 {
8556                 default:
8557                 case Q3DEFORM_PROJECTIONSHADOW:
8558                 case Q3DEFORM_TEXT0:
8559                 case Q3DEFORM_TEXT1:
8560                 case Q3DEFORM_TEXT2:
8561                 case Q3DEFORM_TEXT3:
8562                 case Q3DEFORM_TEXT4:
8563                 case Q3DEFORM_TEXT5:
8564                 case Q3DEFORM_TEXT6:
8565                 case Q3DEFORM_TEXT7:
8566                 case Q3DEFORM_NONE:
8567                         break;
8568                 case Q3DEFORM_AUTOSPRITE:
8569                         dynamicvertex = true;
8570                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8571                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8572                         break;
8573                 case Q3DEFORM_AUTOSPRITE2:
8574                         dynamicvertex = true;
8575                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8576                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8577                         break;
8578                 case Q3DEFORM_NORMAL:
8579                         dynamicvertex = true;
8580                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8581                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8582                         break;
8583                 case Q3DEFORM_WAVE:
8584                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8585                                 break; // if wavefunc is a nop, ignore this transform
8586                         dynamicvertex = true;
8587                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8588                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8589                         break;
8590                 case Q3DEFORM_BULGE:
8591                         dynamicvertex = true;
8592                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8593                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8594                         break;
8595                 case Q3DEFORM_MOVE:
8596                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8597                                 break; // if wavefunc is a nop, ignore this transform
8598                         dynamicvertex = true;
8599                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8600                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8601                         break;
8602                 }
8603         }
8604         switch(rsurface.texture->tcgen.tcgen)
8605         {
8606         default:
8607         case Q3TCGEN_TEXTURE:
8608                 break;
8609         case Q3TCGEN_LIGHTMAP:
8610                 dynamicvertex = true;
8611                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8612                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8613                 break;
8614         case Q3TCGEN_VECTOR:
8615                 dynamicvertex = true;
8616                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8617                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8618                 break;
8619         case Q3TCGEN_ENVIRONMENT:
8620                 dynamicvertex = true;
8621                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8622                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8623                 break;
8624         }
8625         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8626         {
8627                 dynamicvertex = true;
8628                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8629                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8630         }
8631
8632         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8633         {
8634                 dynamicvertex = true;
8635                 batchneed |= BATCHNEED_NOGAPS;
8636                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8637         }
8638
8639         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8640         {
8641                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8642                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8643                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8644                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8645                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8646                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8647                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8648         }
8649
8650         // when the model data has no vertex buffer (dynamic mesh), we need to
8651         // eliminate gaps
8652         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8653                 batchneed |= BATCHNEED_NOGAPS;
8654
8655         // if needsupdate, we have to do a dynamic vertex batch for sure
8656         if (needsupdate & batchneed)
8657                 dynamicvertex = true;
8658
8659         // see if we need to build vertexmesh from arrays
8660         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8661                 dynamicvertex = true;
8662
8663         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8664         // also some drivers strongly dislike firstvertex
8665         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8666                 dynamicvertex = true;
8667
8668         rsurface.batchvertex3f = rsurface.modelvertex3f;
8669         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8670         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8671         rsurface.batchsvector3f = rsurface.modelsvector3f;
8672         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8673         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8674         rsurface.batchtvector3f = rsurface.modeltvector3f;
8675         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8676         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8677         rsurface.batchnormal3f = rsurface.modelnormal3f;
8678         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8679         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8680         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8681         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8682         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8683         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8684         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8685         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8686         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8687         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8688         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8689         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8690         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8691         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8692         rsurface.batchelement3i = rsurface.modelelement3i;
8693         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8694         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8695         rsurface.batchelement3s = rsurface.modelelement3s;
8696         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8697         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8698
8699         // if any dynamic vertex processing has to occur in software, we copy the
8700         // entire surface list together before processing to rebase the vertices
8701         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8702         //
8703         // if any gaps exist and we do not have a static vertex buffer, we have to
8704         // copy the surface list together to avoid wasting upload bandwidth on the
8705         // vertices in the gaps.
8706         //
8707         // if gaps exist and we have a static vertex buffer, we still have to
8708         // combine the index buffer ranges into one dynamic index buffer.
8709         //
8710         // in all cases we end up with data that can be drawn in one call.
8711
8712         if (!dynamicvertex)
8713         {
8714                 // static vertex data, just set pointers...
8715                 rsurface.batchgeneratedvertex = false;
8716                 // if there are gaps, we want to build a combined index buffer,
8717                 // otherwise use the original static buffer with an appropriate offset
8718                 if (gaps)
8719                 {
8720                         // build a new triangle elements array for this batch
8721                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8722                         rsurface.batchfirsttriangle = 0;
8723                         numtriangles = 0;
8724                         for (i = 0;i < texturenumsurfaces;i++)
8725                         {
8726                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8727                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8728                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8729                                 numtriangles += surfacenumtriangles;
8730                         }
8731                         rsurface.batchelement3i_indexbuffer = NULL;
8732                         rsurface.batchelement3i_bufferoffset = 0;
8733                         rsurface.batchelement3s = NULL;
8734                         rsurface.batchelement3s_indexbuffer = NULL;
8735                         rsurface.batchelement3s_bufferoffset = 0;
8736                         if (endvertex <= 65536)
8737                         {
8738                                 // make a 16bit (unsigned short) index array if possible
8739                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8740                                 for (i = 0;i < numtriangles*3;i++)
8741                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8742                         }
8743                 }
8744                 return;
8745         }
8746
8747         // something needs software processing, do it for real...
8748         // we only directly handle separate array data in this case and then
8749         // generate interleaved data if needed...
8750         rsurface.batchgeneratedvertex = true;
8751
8752         // now copy the vertex data into a combined array and make an index array
8753         // (this is what Quake3 does all the time)
8754         //if (gaps || rsurface.batchfirstvertex)
8755         {
8756                 rsurface.batchvertex3fbuffer = NULL;
8757                 rsurface.batchvertexmesh = NULL;
8758                 rsurface.batchvertexmeshbuffer = NULL;
8759                 rsurface.batchvertex3f = NULL;
8760                 rsurface.batchvertex3f_vertexbuffer = NULL;
8761                 rsurface.batchvertex3f_bufferoffset = 0;
8762                 rsurface.batchsvector3f = NULL;
8763                 rsurface.batchsvector3f_vertexbuffer = NULL;
8764                 rsurface.batchsvector3f_bufferoffset = 0;
8765                 rsurface.batchtvector3f = NULL;
8766                 rsurface.batchtvector3f_vertexbuffer = NULL;
8767                 rsurface.batchtvector3f_bufferoffset = 0;
8768                 rsurface.batchnormal3f = NULL;
8769                 rsurface.batchnormal3f_vertexbuffer = NULL;
8770                 rsurface.batchnormal3f_bufferoffset = 0;
8771                 rsurface.batchlightmapcolor4f = NULL;
8772                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8773                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8774                 rsurface.batchtexcoordtexture2f = NULL;
8775                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8776                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8777                 rsurface.batchtexcoordlightmap2f = NULL;
8778                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8779                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8780                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8781                 rsurface.batchelement3i_indexbuffer = NULL;
8782                 rsurface.batchelement3i_bufferoffset = 0;
8783                 rsurface.batchelement3s = NULL;
8784                 rsurface.batchelement3s_indexbuffer = NULL;
8785                 rsurface.batchelement3s_bufferoffset = 0;
8786                 // we'll only be setting up certain arrays as needed
8787                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8788                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8789                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8790                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8791                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8792                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8793                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8794                 {
8795                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8796                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797                 }
8798                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8799                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8800                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8801                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8802                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8803                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8804                 numvertices = 0;
8805                 numtriangles = 0;
8806                 for (i = 0;i < texturenumsurfaces;i++)
8807                 {
8808                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8809                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8810                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8811                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8812                         // copy only the data requested
8813                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8814                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8815                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8816                         {
8817                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8818                                 {
8819                                         if (rsurface.batchvertex3f)
8820                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8821                                         else
8822                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8823                                 }
8824                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8825                                 {
8826                                         if (rsurface.modelnormal3f)
8827                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8828                                         else
8829                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8830                                 }
8831                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8832                                 {
8833                                         if (rsurface.modelsvector3f)
8834                                         {
8835                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8836                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8837                                         }
8838                                         else
8839                                         {
8840                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8841                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8842                                         }
8843                                 }
8844                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8845                                 {
8846                                         if (rsurface.modellightmapcolor4f)
8847                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8848                                         else
8849                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8850                                 }
8851                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8852                                 {
8853                                         if (rsurface.modeltexcoordtexture2f)
8854                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8855                                         else
8856                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8857                                 }
8858                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8859                                 {
8860                                         if (rsurface.modeltexcoordlightmap2f)
8861                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8862                                         else
8863                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8864                                 }
8865                         }
8866                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8867                         numvertices += surfacenumvertices;
8868                         numtriangles += surfacenumtriangles;
8869                 }
8870
8871                 // generate a 16bit index array as well if possible
8872                 // (in general, dynamic batches fit)
8873                 if (numvertices <= 65536)
8874                 {
8875                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8876                         for (i = 0;i < numtriangles*3;i++)
8877                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8878                 }
8879
8880                 // since we've copied everything, the batch now starts at 0
8881                 rsurface.batchfirstvertex = 0;
8882                 rsurface.batchnumvertices = batchnumvertices;
8883                 rsurface.batchfirsttriangle = 0;
8884                 rsurface.batchnumtriangles = batchnumtriangles;
8885         }
8886
8887         // q1bsp surfaces rendered in vertex color mode have to have colors
8888         // calculated based on lightstyles
8889         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8890         {
8891                 // generate color arrays for the surfaces in this list
8892                 int c[4];
8893                 int scale;
8894                 int size3;
8895                 const int *offsets;
8896                 const unsigned char *lm;
8897                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8898                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8899                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8900                 numvertices = 0;
8901                 for (i = 0;i < texturenumsurfaces;i++)
8902                 {
8903                         surface = texturesurfacelist[i];
8904                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8905                         surfacenumvertices = surface->num_vertices;
8906                         if (surface->lightmapinfo->samples)
8907                         {
8908                                 for (j = 0;j < surfacenumvertices;j++)
8909                                 {
8910                                         lm = surface->lightmapinfo->samples + offsets[j];
8911                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8912                                         VectorScale(lm, scale, c);
8913                                         if (surface->lightmapinfo->styles[1] != 255)
8914                                         {
8915                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8916                                                 lm += size3;
8917                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8918                                                 VectorMA(c, scale, lm, c);
8919                                                 if (surface->lightmapinfo->styles[2] != 255)
8920                                                 {
8921                                                         lm += size3;
8922                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8923                                                         VectorMA(c, scale, lm, c);
8924                                                         if (surface->lightmapinfo->styles[3] != 255)
8925                                                         {
8926                                                                 lm += size3;
8927                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8928                                                                 VectorMA(c, scale, lm, c);
8929                                                         }
8930                                                 }
8931                                         }
8932                                         c[0] >>= 7;
8933                                         c[1] >>= 7;
8934                                         c[2] >>= 7;
8935                                         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);
8936                                         numvertices++;
8937                                 }
8938                         }
8939                         else
8940                         {
8941                                 for (j = 0;j < surfacenumvertices;j++)
8942                                 {
8943                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8944                                         numvertices++;
8945                                 }
8946                         }
8947                 }
8948         }
8949
8950         // if vertices are deformed (sprite flares and things in maps, possibly
8951         // water waves, bulges and other deformations), modify the copied vertices
8952         // in place
8953         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8954         {
8955                 switch (deform->deform)
8956                 {
8957                 default:
8958                 case Q3DEFORM_PROJECTIONSHADOW:
8959                 case Q3DEFORM_TEXT0:
8960                 case Q3DEFORM_TEXT1:
8961                 case Q3DEFORM_TEXT2:
8962                 case Q3DEFORM_TEXT3:
8963                 case Q3DEFORM_TEXT4:
8964                 case Q3DEFORM_TEXT5:
8965                 case Q3DEFORM_TEXT6:
8966                 case Q3DEFORM_TEXT7:
8967                 case Q3DEFORM_NONE:
8968                         break;
8969                 case Q3DEFORM_AUTOSPRITE:
8970                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8971                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8972                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8973                         VectorNormalize(newforward);
8974                         VectorNormalize(newright);
8975                         VectorNormalize(newup);
8976 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8977 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8978 //                      rsurface.batchvertex3f_bufferoffset = 0;
8979 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8980 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8981 //                      rsurface.batchsvector3f_bufferoffset = 0;
8982 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8983 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8984 //                      rsurface.batchtvector3f_bufferoffset = 0;
8985 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8986 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8987 //                      rsurface.batchnormal3f_bufferoffset = 0;
8988                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8989                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8990                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8991                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8992                                 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);
8993                         // a single autosprite surface can contain multiple sprites...
8994                         for (j = 0;j < batchnumvertices - 3;j += 4)
8995                         {
8996                                 VectorClear(center);
8997                                 for (i = 0;i < 4;i++)
8998                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8999                                 VectorScale(center, 0.25f, center);
9000                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9001                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9002                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9003                                 for (i = 0;i < 4;i++)
9004                                 {
9005                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9006                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9007                                 }
9008                         }
9009                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9010                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9011                         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);
9012                         break;
9013                 case Q3DEFORM_AUTOSPRITE2:
9014                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9015                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9016                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9017                         VectorNormalize(newforward);
9018                         VectorNormalize(newright);
9019                         VectorNormalize(newup);
9020 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9021 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9022 //                      rsurface.batchvertex3f_bufferoffset = 0;
9023                         {
9024                                 const float *v1, *v2;
9025                                 vec3_t start, end;
9026                                 float f, l;
9027                                 struct
9028                                 {
9029                                         float length2;
9030                                         const float *v1;
9031                                         const float *v2;
9032                                 }
9033                                 shortest[2];
9034                                 memset(shortest, 0, sizeof(shortest));
9035                                 // a single autosprite surface can contain multiple sprites...
9036                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9037                                 {
9038                                         VectorClear(center);
9039                                         for (i = 0;i < 4;i++)
9040                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9041                                         VectorScale(center, 0.25f, center);
9042                                         // find the two shortest edges, then use them to define the
9043                                         // axis vectors for rotating around the central axis
9044                                         for (i = 0;i < 6;i++)
9045                                         {
9046                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9047                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9048                                                 l = VectorDistance2(v1, v2);
9049                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9050                                                 if (v1[2] != v2[2])
9051                                                         l += (1.0f / 1024.0f);
9052                                                 if (shortest[0].length2 > l || i == 0)
9053                                                 {
9054                                                         shortest[1] = shortest[0];
9055                                                         shortest[0].length2 = l;
9056                                                         shortest[0].v1 = v1;
9057                                                         shortest[0].v2 = v2;
9058                                                 }
9059                                                 else if (shortest[1].length2 > l || i == 1)
9060                                                 {
9061                                                         shortest[1].length2 = l;
9062                                                         shortest[1].v1 = v1;
9063                                                         shortest[1].v2 = v2;
9064                                                 }
9065                                         }
9066                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9067                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9068                                         // this calculates the right vector from the shortest edge
9069                                         // and the up vector from the edge midpoints
9070                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9071                                         VectorNormalize(right);
9072                                         VectorSubtract(end, start, up);
9073                                         VectorNormalize(up);
9074                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9075                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9076                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9077                                         VectorNegate(forward, forward);
9078                                         VectorReflect(forward, 0, up, forward);
9079                                         VectorNormalize(forward);
9080                                         CrossProduct(up, forward, newright);
9081                                         VectorNormalize(newright);
9082                                         // rotate the quad around the up axis vector, this is made
9083                                         // especially easy by the fact we know the quad is flat,
9084                                         // so we only have to subtract the center position and
9085                                         // measure distance along the right vector, and then
9086                                         // multiply that by the newright vector and add back the
9087                                         // center position
9088                                         // we also need to subtract the old position to undo the
9089                                         // displacement from the center, which we do with a
9090                                         // DotProduct, the subtraction/addition of center is also
9091                                         // optimized into DotProducts here
9092                                         l = DotProduct(right, center);
9093                                         for (i = 0;i < 4;i++)
9094                                         {
9095                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9096                                                 f = DotProduct(right, v1) - l;
9097                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9098                                         }
9099                                 }
9100                         }
9101                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9102                         {
9103 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9104 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9105 //                              rsurface.batchnormal3f_bufferoffset = 0;
9106                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9107                         }
9108                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9109                         {
9110 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9111 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9112 //                              rsurface.batchsvector3f_bufferoffset = 0;
9113 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9114 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9115 //                              rsurface.batchtvector3f_bufferoffset = 0;
9116                                 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);
9117                         }
9118                         break;
9119                 case Q3DEFORM_NORMAL:
9120                         // deform the normals to make reflections wavey
9121                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9122                         rsurface.batchnormal3f_vertexbuffer = NULL;
9123                         rsurface.batchnormal3f_bufferoffset = 0;
9124                         for (j = 0;j < batchnumvertices;j++)
9125                         {
9126                                 float vertex[3];
9127                                 float *normal = rsurface.batchnormal3f + 3*j;
9128                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9129                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9130                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9131                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9132                                 VectorNormalize(normal);
9133                         }
9134                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9135                         {
9136 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9137 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9138 //                              rsurface.batchsvector3f_bufferoffset = 0;
9139 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9140 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9141 //                              rsurface.batchtvector3f_bufferoffset = 0;
9142                                 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);
9143                         }
9144                         break;
9145                 case Q3DEFORM_WAVE:
9146                         // deform vertex array to make wavey water and flags and such
9147                         waveparms[0] = deform->waveparms[0];
9148                         waveparms[1] = deform->waveparms[1];
9149                         waveparms[2] = deform->waveparms[2];
9150                         waveparms[3] = deform->waveparms[3];
9151                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9152                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9153                         // this is how a divisor of vertex influence on deformation
9154                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9155                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9156 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9157 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9158 //                      rsurface.batchvertex3f_bufferoffset = 0;
9159 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9160 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9161 //                      rsurface.batchnormal3f_bufferoffset = 0;
9162                         for (j = 0;j < batchnumvertices;j++)
9163                         {
9164                                 // if the wavefunc depends on time, evaluate it per-vertex
9165                                 if (waveparms[3])
9166                                 {
9167                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9168                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9169                                 }
9170                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9171                         }
9172                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9173                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9174                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9175                         {
9176 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9178 //                              rsurface.batchsvector3f_bufferoffset = 0;
9179 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9180 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9181 //                              rsurface.batchtvector3f_bufferoffset = 0;
9182                                 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);
9183                         }
9184                         break;
9185                 case Q3DEFORM_BULGE:
9186                         // deform vertex array to make the surface have moving bulges
9187 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9188 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9189 //                      rsurface.batchvertex3f_bufferoffset = 0;
9190 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9191 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9192 //                      rsurface.batchnormal3f_bufferoffset = 0;
9193                         for (j = 0;j < batchnumvertices;j++)
9194                         {
9195                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9196                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9197                         }
9198                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9199                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9200                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9201                         {
9202 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9203 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9204 //                              rsurface.batchsvector3f_bufferoffset = 0;
9205 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9206 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9207 //                              rsurface.batchtvector3f_bufferoffset = 0;
9208                                 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);
9209                         }
9210                         break;
9211                 case Q3DEFORM_MOVE:
9212                         // deform vertex array
9213                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9214                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9215                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9216                         VectorScale(deform->parms, scale, waveparms);
9217 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9218 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9219 //                      rsurface.batchvertex3f_bufferoffset = 0;
9220                         for (j = 0;j < batchnumvertices;j++)
9221                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9222                         break;
9223                 }
9224         }
9225
9226         // generate texcoords based on the chosen texcoord source
9227         switch(rsurface.texture->tcgen.tcgen)
9228         {
9229         default:
9230         case Q3TCGEN_TEXTURE:
9231                 break;
9232         case Q3TCGEN_LIGHTMAP:
9233 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9234 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9235 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9236                 if (rsurface.batchtexcoordlightmap2f)
9237                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9238                 break;
9239         case Q3TCGEN_VECTOR:
9240 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9241 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9242 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9243                 for (j = 0;j < batchnumvertices;j++)
9244                 {
9245                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9246                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9247                 }
9248                 break;
9249         case Q3TCGEN_ENVIRONMENT:
9250                 // make environment reflections using a spheremap
9251                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9252                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9253                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9254                 for (j = 0;j < batchnumvertices;j++)
9255                 {
9256                         // identical to Q3A's method, but executed in worldspace so
9257                         // carried models can be shiny too
9258
9259                         float viewer[3], d, reflected[3], worldreflected[3];
9260
9261                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9262                         // VectorNormalize(viewer);
9263
9264                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9265
9266                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9267                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9268                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9269                         // note: this is proportinal to viewer, so we can normalize later
9270
9271                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9272                         VectorNormalize(worldreflected);
9273
9274                         // note: this sphere map only uses world x and z!
9275                         // so positive and negative y will LOOK THE SAME.
9276                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9277                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9278                 }
9279                 break;
9280         }
9281         // the only tcmod that needs software vertex processing is turbulent, so
9282         // check for it here and apply the changes if needed
9283         // and we only support that as the first one
9284         // (handling a mixture of turbulent and other tcmods would be problematic
9285         //  without punting it entirely to a software path)
9286         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9287         {
9288                 amplitude = rsurface.texture->tcmods[0].parms[1];
9289                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9290 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9291 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9292 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9293                 for (j = 0;j < batchnumvertices;j++)
9294                 {
9295                         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);
9296                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9297                 }
9298         }
9299
9300         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9301         {
9302                 // convert the modified arrays to vertex structs
9303 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9304 //              rsurface.batchvertexmeshbuffer = NULL;
9305                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9306                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9307                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9308                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9309                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9310                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9311                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9312                 {
9313                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9314                         {
9315                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9316                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9317                         }
9318                 }
9319                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9320                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9321                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9322                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9323                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9324                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9325                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9326                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9327                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9328         }
9329 }
9330
9331 void RSurf_DrawBatch(void)
9332 {
9333         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9334         // through the pipeline, killing it earlier in the pipeline would have
9335         // per-surface overhead rather than per-batch overhead, so it's best to
9336         // reject it here, before it hits glDraw.
9337         if (rsurface.batchnumtriangles == 0)
9338                 return;
9339 #if 0
9340         // batch debugging code
9341         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9342         {
9343                 int i;
9344                 int j;
9345                 int c;
9346                 const int *e;
9347                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9348                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9349                 {
9350                         c = e[i];
9351                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9352                         {
9353                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9354                                 {
9355                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9356                                                 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);
9357                                         break;
9358                                 }
9359                         }
9360                 }
9361         }
9362 #endif
9363         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);
9364 }
9365
9366 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9367 {
9368         // pick the closest matching water plane
9369         int planeindex, vertexindex, bestplaneindex = -1;
9370         float d, bestd;
9371         vec3_t vert;
9372         const float *v;
9373         r_waterstate_waterplane_t *p;
9374         qboolean prepared = false;
9375         bestd = 0;
9376         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9377         {
9378                 if(p->camera_entity != rsurface.texture->camera_entity)
9379                         continue;
9380                 d = 0;
9381                 if(!prepared)
9382                 {
9383                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9384                         prepared = true;
9385                         if(rsurface.batchnumvertices == 0)
9386                                 break;
9387                 }
9388                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9389                 {
9390                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9391                         d += fabs(PlaneDiff(vert, &p->plane));
9392                 }
9393                 if (bestd > d || bestplaneindex < 0)
9394                 {
9395                         bestd = d;
9396                         bestplaneindex = planeindex;
9397                 }
9398         }
9399         return bestplaneindex;
9400         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9401         // this situation though, as it might be better to render single larger
9402         // batches with useless stuff (backface culled for example) than to
9403         // render multiple smaller batches
9404 }
9405
9406 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9407 {
9408         int i;
9409         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9410         rsurface.passcolor4f_vertexbuffer = 0;
9411         rsurface.passcolor4f_bufferoffset = 0;
9412         for (i = 0;i < rsurface.batchnumvertices;i++)
9413                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9414 }
9415
9416 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9417 {
9418         int i;
9419         float f;
9420         const float *v;
9421         const float *c;
9422         float *c2;
9423         if (rsurface.passcolor4f)
9424         {
9425                 // generate color arrays
9426                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9427                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9428                 rsurface.passcolor4f_vertexbuffer = 0;
9429                 rsurface.passcolor4f_bufferoffset = 0;
9430                 for (i = 0, 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)
9431                 {
9432                         f = RSurf_FogVertex(v);
9433                         c2[0] = c[0] * f;
9434                         c2[1] = c[1] * f;
9435                         c2[2] = c[2] * f;
9436                         c2[3] = c[3];
9437                 }
9438         }
9439         else
9440         {
9441                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9442                 rsurface.passcolor4f_vertexbuffer = 0;
9443                 rsurface.passcolor4f_bufferoffset = 0;
9444                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9445                 {
9446                         f = RSurf_FogVertex(v);
9447                         c2[0] = f;
9448                         c2[1] = f;
9449                         c2[2] = f;
9450                         c2[3] = 1;
9451                 }
9452         }
9453 }
9454
9455 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9456 {
9457         int i;
9458         float f;
9459         const float *v;
9460         const float *c;
9461         float *c2;
9462         if (!rsurface.passcolor4f)
9463                 return;
9464         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9465         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9466         rsurface.passcolor4f_vertexbuffer = 0;
9467         rsurface.passcolor4f_bufferoffset = 0;
9468         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)
9469         {
9470                 f = RSurf_FogVertex(v);
9471                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9472                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9473                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9474                 c2[3] = c[3];
9475         }
9476 }
9477
9478 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9479 {
9480         int i;
9481         const float *c;
9482         float *c2;
9483         if (!rsurface.passcolor4f)
9484                 return;
9485         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9486         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9487         rsurface.passcolor4f_vertexbuffer = 0;
9488         rsurface.passcolor4f_bufferoffset = 0;
9489         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9490         {
9491                 c2[0] = c[0] * r;
9492                 c2[1] = c[1] * g;
9493                 c2[2] = c[2] * b;
9494                 c2[3] = c[3] * a;
9495         }
9496 }
9497
9498 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9499 {
9500         int i;
9501         const float *c;
9502         float *c2;
9503         if (!rsurface.passcolor4f)
9504                 return;
9505         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9506         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9507         rsurface.passcolor4f_vertexbuffer = 0;
9508         rsurface.passcolor4f_bufferoffset = 0;
9509         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9510         {
9511                 c2[0] = c[0] + r_refdef.scene.ambient;
9512                 c2[1] = c[1] + r_refdef.scene.ambient;
9513                 c2[2] = c[2] + r_refdef.scene.ambient;
9514                 c2[3] = c[3];
9515         }
9516 }
9517
9518 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9519 {
9520         // TODO: optimize
9521         rsurface.passcolor4f = NULL;
9522         rsurface.passcolor4f_vertexbuffer = 0;
9523         rsurface.passcolor4f_bufferoffset = 0;
9524         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9525         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9526         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9527         GL_Color(r, g, b, a);
9528         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9529         RSurf_DrawBatch();
9530 }
9531
9532 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9533 {
9534         // TODO: optimize applyfog && applycolor case
9535         // just apply fog if necessary, and tint the fog color array if necessary
9536         rsurface.passcolor4f = NULL;
9537         rsurface.passcolor4f_vertexbuffer = 0;
9538         rsurface.passcolor4f_bufferoffset = 0;
9539         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9540         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9541         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9542         GL_Color(r, g, b, a);
9543         RSurf_DrawBatch();
9544 }
9545
9546 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9547 {
9548         // TODO: optimize
9549         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9550         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9551         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9552         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9553         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9554         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9555         GL_Color(r, g, b, a);
9556         RSurf_DrawBatch();
9557 }
9558
9559 static void RSurf_DrawBatch_GL11_ClampColor(void)
9560 {
9561         int i;
9562         const float *c1;
9563         float *c2;
9564         if (!rsurface.passcolor4f)
9565                 return;
9566         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9567         {
9568                 c2[0] = bound(0.0f, c1[0], 1.0f);
9569                 c2[1] = bound(0.0f, c1[1], 1.0f);
9570                 c2[2] = bound(0.0f, c1[2], 1.0f);
9571                 c2[3] = bound(0.0f, c1[3], 1.0f);
9572         }
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9576 {
9577         int i;
9578         float f;
9579         const float *v;
9580         const float *n;
9581         float *c;
9582         //vec3_t eyedir;
9583
9584         // fake shading
9585         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9586         rsurface.passcolor4f_vertexbuffer = 0;
9587         rsurface.passcolor4f_bufferoffset = 0;
9588         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)
9589         {
9590                 f = -DotProduct(r_refdef.view.forward, n);
9591                 f = max(0, f);
9592                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9593                 f *= r_refdef.lightmapintensity;
9594                 Vector4Set(c, f, f, f, 1);
9595         }
9596 }
9597
9598 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9599 {
9600         RSurf_DrawBatch_GL11_ApplyFakeLight();
9601         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9602         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9603         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9604         GL_Color(r, g, b, a);
9605         RSurf_DrawBatch();
9606 }
9607
9608 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9609 {
9610         int i;
9611         float f;
9612         float alpha;
9613         const float *v;
9614         const float *n;
9615         float *c;
9616         vec3_t ambientcolor;
9617         vec3_t diffusecolor;
9618         vec3_t lightdir;
9619         // TODO: optimize
9620         // model lighting
9621         VectorCopy(rsurface.modellight_lightdir, lightdir);
9622         f = 0.5f * r_refdef.lightmapintensity;
9623         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9624         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9625         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9626         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9627         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9628         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9629         alpha = *a;
9630         if (VectorLength2(diffusecolor) > 0)
9631         {
9632                 // q3-style directional shading
9633                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9634                 rsurface.passcolor4f_vertexbuffer = 0;
9635                 rsurface.passcolor4f_bufferoffset = 0;
9636                 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)
9637                 {
9638                         if ((f = DotProduct(n, lightdir)) > 0)
9639                                 VectorMA(ambientcolor, f, diffusecolor, c);
9640                         else
9641                                 VectorCopy(ambientcolor, c);
9642                         c[3] = alpha;
9643                 }
9644                 *r = 1;
9645                 *g = 1;
9646                 *b = 1;
9647                 *a = 1;
9648                 *applycolor = false;
9649         }
9650         else
9651         {
9652                 *r = ambientcolor[0];
9653                 *g = ambientcolor[1];
9654                 *b = ambientcolor[2];
9655                 rsurface.passcolor4f = NULL;
9656                 rsurface.passcolor4f_vertexbuffer = 0;
9657                 rsurface.passcolor4f_bufferoffset = 0;
9658         }
9659 }
9660
9661 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9662 {
9663         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9664         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9665         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9666         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9667         GL_Color(r, g, b, a);
9668         RSurf_DrawBatch();
9669 }
9670
9671 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9672 {
9673         int i;
9674         float f;
9675         const float *v;
9676         float *c;
9677
9678         // fake shading
9679         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9680         rsurface.passcolor4f_vertexbuffer = 0;
9681         rsurface.passcolor4f_bufferoffset = 0;
9682
9683         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9684         {
9685                 f = 1 - RSurf_FogVertex(v);
9686                 c[0] = r;
9687                 c[1] = g;
9688                 c[2] = b;
9689                 c[3] = f * a;
9690         }
9691 }
9692
9693 void RSurf_SetupDepthAndCulling(void)
9694 {
9695         // submodels are biased to avoid z-fighting with world surfaces that they
9696         // may be exactly overlapping (avoids z-fighting artifacts on certain
9697         // doors and things in Quake maps)
9698         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9699         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9700         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9701         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9702 }
9703
9704 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9705 {
9706         // transparent sky would be ridiculous
9707         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9708                 return;
9709         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9710         skyrenderlater = true;
9711         RSurf_SetupDepthAndCulling();
9712         GL_DepthMask(true);
9713         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9714         // skymasking on them, and Quake3 never did sky masking (unlike
9715         // software Quake and software Quake2), so disable the sky masking
9716         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9717         // and skymasking also looks very bad when noclipping outside the
9718         // level, so don't use it then either.
9719         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9720         {
9721                 R_Mesh_ResetTextureState();
9722                 if (skyrendermasked)
9723                 {
9724                         R_SetupShader_DepthOrShadow(false);
9725                         // depth-only (masking)
9726                         GL_ColorMask(0,0,0,0);
9727                         // just to make sure that braindead drivers don't draw
9728                         // anything despite that colormask...
9729                         GL_BlendFunc(GL_ZERO, GL_ONE);
9730                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9731                         if (rsurface.batchvertex3fbuffer)
9732                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9733                         else
9734                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9735                 }
9736                 else
9737                 {
9738                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9739                         // fog sky
9740                         GL_BlendFunc(GL_ONE, GL_ZERO);
9741                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9742                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9743                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9744                 }
9745                 RSurf_DrawBatch();
9746                 if (skyrendermasked)
9747                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9748         }
9749         R_Mesh_ResetTextureState();
9750         GL_Color(1, 1, 1, 1);
9751 }
9752
9753 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9754 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9755 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9756 {
9757         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9758                 return;
9759         if (prepass)
9760         {
9761                 // render screenspace normalmap to texture
9762                 GL_DepthMask(true);
9763                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9764                 RSurf_DrawBatch();
9765         }
9766
9767         // bind lightmap texture
9768
9769         // water/refraction/reflection/camera surfaces have to be handled specially
9770         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9771         {
9772                 int start, end, startplaneindex;
9773                 for (start = 0;start < texturenumsurfaces;start = end)
9774                 {
9775                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9776                         if(startplaneindex < 0)
9777                         {
9778                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9779                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9780                                 end = start + 1;
9781                                 continue;
9782                         }
9783                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9784                                 ;
9785                         // now that we have a batch using the same planeindex, render it
9786                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9787                         {
9788                                 // render water or distortion background
9789                                 GL_DepthMask(true);
9790                                 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);
9791                                 RSurf_DrawBatch();
9792                                 // blend surface on top
9793                                 GL_DepthMask(false);
9794                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9795                                 RSurf_DrawBatch();
9796                         }
9797                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9798                         {
9799                                 // render surface with reflection texture as input
9800                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9801                                 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);
9802                                 RSurf_DrawBatch();
9803                         }
9804                 }
9805                 return;
9806         }
9807
9808         // render surface batch normally
9809         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9810         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);
9811         RSurf_DrawBatch();
9812 }
9813
9814 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9815 {
9816         // OpenGL 1.3 path - anything not completely ancient
9817         qboolean applycolor;
9818         qboolean applyfog;
9819         int layerindex;
9820         const texturelayer_t *layer;
9821         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);
9822         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9823
9824         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9825         {
9826                 vec4_t layercolor;
9827                 int layertexrgbscale;
9828                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9829                 {
9830                         if (layerindex == 0)
9831                                 GL_AlphaTest(true);
9832                         else
9833                         {
9834                                 GL_AlphaTest(false);
9835                                 GL_DepthFunc(GL_EQUAL);
9836                         }
9837                 }
9838                 GL_DepthMask(layer->depthmask && writedepth);
9839                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9840                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9841                 {
9842                         layertexrgbscale = 4;
9843                         VectorScale(layer->color, 0.25f, layercolor);
9844                 }
9845                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9846                 {
9847                         layertexrgbscale = 2;
9848                         VectorScale(layer->color, 0.5f, layercolor);
9849                 }
9850                 else
9851                 {
9852                         layertexrgbscale = 1;
9853                         VectorScale(layer->color, 1.0f, layercolor);
9854                 }
9855                 layercolor[3] = layer->color[3];
9856                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9857                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9858                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9859                 switch (layer->type)
9860                 {
9861                 case TEXTURELAYERTYPE_LITTEXTURE:
9862                         // single-pass lightmapped texture with 2x rgbscale
9863                         R_Mesh_TexBind(0, r_texture_white);
9864                         R_Mesh_TexMatrix(0, NULL);
9865                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9866                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9867                         R_Mesh_TexBind(1, layer->texture);
9868                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9869                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9870                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9871                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9872                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9873                         else if (FAKELIGHT_ENABLED)
9874                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9875                         else if (rsurface.uselightmaptexture)
9876                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9877                         else
9878                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9879                         break;
9880                 case TEXTURELAYERTYPE_TEXTURE:
9881                         // singletexture unlit texture with transparency support
9882                         R_Mesh_TexBind(0, layer->texture);
9883                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9884                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9885                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9886                         R_Mesh_TexBind(1, 0);
9887                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9888                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9889                         break;
9890                 case TEXTURELAYERTYPE_FOG:
9891                         // singletexture fogging
9892                         if (layer->texture)
9893                         {
9894                                 R_Mesh_TexBind(0, layer->texture);
9895                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9897                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898                         }
9899                         else
9900                         {
9901                                 R_Mesh_TexBind(0, 0);
9902                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9903                         }
9904                         R_Mesh_TexBind(1, 0);
9905                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9906                         // generate a color array for the fog pass
9907                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9908                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9909                         RSurf_DrawBatch();
9910                         break;
9911                 default:
9912                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9913                 }
9914         }
9915         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9916         {
9917                 GL_DepthFunc(GL_LEQUAL);
9918                 GL_AlphaTest(false);
9919         }
9920 }
9921
9922 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9923 {
9924         // OpenGL 1.1 - crusty old voodoo path
9925         qboolean applyfog;
9926         int layerindex;
9927         const texturelayer_t *layer;
9928         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);
9929         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9930
9931         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9932         {
9933                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9934                 {
9935                         if (layerindex == 0)
9936                                 GL_AlphaTest(true);
9937                         else
9938                         {
9939                                 GL_AlphaTest(false);
9940                                 GL_DepthFunc(GL_EQUAL);
9941                         }
9942                 }
9943                 GL_DepthMask(layer->depthmask && writedepth);
9944                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9945                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9946                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9947                 switch (layer->type)
9948                 {
9949                 case TEXTURELAYERTYPE_LITTEXTURE:
9950                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9951                         {
9952                                 // two-pass lit texture with 2x rgbscale
9953                                 // first the lightmap pass
9954                                 R_Mesh_TexBind(0, r_texture_white);
9955                                 R_Mesh_TexMatrix(0, NULL);
9956                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9957                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9958                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9959                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9960                                 else if (FAKELIGHT_ENABLED)
9961                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9962                                 else if (rsurface.uselightmaptexture)
9963                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9964                                 else
9965                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9966                                 // then apply the texture to it
9967                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9968                                 R_Mesh_TexBind(0, layer->texture);
9969                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9970                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9971                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9972                                 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);
9973                         }
9974                         else
9975                         {
9976                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9977                                 R_Mesh_TexBind(0, layer->texture);
9978                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9979                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9980                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9981                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9982                                         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);
9983                                 else
9984                                         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);
9985                         }
9986                         break;
9987                 case TEXTURELAYERTYPE_TEXTURE:
9988                         // singletexture unlit texture with transparency support
9989                         R_Mesh_TexBind(0, layer->texture);
9990                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9991                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9992                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9993                         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);
9994                         break;
9995                 case TEXTURELAYERTYPE_FOG:
9996                         // singletexture fogging
9997                         if (layer->texture)
9998                         {
9999                                 R_Mesh_TexBind(0, layer->texture);
10000                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10001                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10002                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10003                         }
10004                         else
10005                         {
10006                                 R_Mesh_TexBind(0, 0);
10007                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10008                         }
10009                         // generate a color array for the fog pass
10010                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10011                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10012                         RSurf_DrawBatch();
10013                         break;
10014                 default:
10015                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10016                 }
10017         }
10018         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10019         {
10020                 GL_DepthFunc(GL_LEQUAL);
10021                 GL_AlphaTest(false);
10022         }
10023 }
10024
10025 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10026 {
10027         int vi;
10028         int j;
10029         r_vertexgeneric_t *batchvertex;
10030         float c[4];
10031
10032 //      R_Mesh_ResetTextureState();
10033         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10034
10035         if(rsurface.texture && rsurface.texture->currentskinframe)
10036         {
10037                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10038                 c[3] *= rsurface.texture->currentalpha;
10039         }
10040         else
10041         {
10042                 c[0] = 1;
10043                 c[1] = 0;
10044                 c[2] = 1;
10045                 c[3] = 1;
10046         }
10047
10048         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10049         {
10050                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10051                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10052                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10053         }
10054
10055         // brighten it up (as texture value 127 means "unlit")
10056         c[0] *= 2 * r_refdef.view.colorscale;
10057         c[1] *= 2 * r_refdef.view.colorscale;
10058         c[2] *= 2 * r_refdef.view.colorscale;
10059
10060         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10061                 c[3] *= r_wateralpha.value;
10062
10063         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10064         {
10065                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10066                 GL_DepthMask(false);
10067         }
10068         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10069         {
10070                 GL_BlendFunc(GL_ONE, GL_ONE);
10071                 GL_DepthMask(false);
10072         }
10073         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10074         {
10075                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10076                 GL_DepthMask(false);
10077         }
10078         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10079         {
10080                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10081                 GL_DepthMask(false);
10082         }
10083         else
10084         {
10085                 GL_BlendFunc(GL_ONE, GL_ZERO);
10086                 GL_DepthMask(writedepth);
10087         }
10088
10089         if (r_showsurfaces.integer == 3)
10090         {
10091                 rsurface.passcolor4f = NULL;
10092
10093                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10094                 {
10095                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10096
10097                         rsurface.passcolor4f = NULL;
10098                         rsurface.passcolor4f_vertexbuffer = 0;
10099                         rsurface.passcolor4f_bufferoffset = 0;
10100                 }
10101                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10102                 {
10103                         qboolean applycolor = true;
10104                         float one = 1.0;
10105
10106                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10107
10108                         r_refdef.lightmapintensity = 1;
10109                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10110                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10111                 }
10112                 else if (FAKELIGHT_ENABLED)
10113                 {
10114                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10115
10116                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10117                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10118                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10119                 }
10120                 else
10121                 {
10122                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10123
10124                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10125                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10126                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10127                 }
10128
10129                 if(!rsurface.passcolor4f)
10130                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10131
10132                 RSurf_DrawBatch_GL11_ApplyAmbient();
10133                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10134                 if(r_refdef.fogenabled)
10135                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10136                 RSurf_DrawBatch_GL11_ClampColor();
10137
10138                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10139                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10140                 RSurf_DrawBatch();
10141         }
10142         else if (!r_refdef.view.showdebug)
10143         {
10144                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10145                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10146                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10147                 {
10148                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10149                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10150                 }
10151                 R_Mesh_PrepareVertices_Generic_Unlock();
10152                 RSurf_DrawBatch();
10153         }
10154         else if (r_showsurfaces.integer == 4)
10155         {
10156                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10157                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10158                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10159                 {
10160                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10161                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10162                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10163                 }
10164                 R_Mesh_PrepareVertices_Generic_Unlock();
10165                 RSurf_DrawBatch();
10166         }
10167         else if (r_showsurfaces.integer == 2)
10168         {
10169                 const int *e;
10170                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10171                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10172                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10173                 {
10174                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10175                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10176                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10177                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10178                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10179                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10180                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10181                 }
10182                 R_Mesh_PrepareVertices_Generic_Unlock();
10183                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10184         }
10185         else
10186         {
10187                 int texturesurfaceindex;
10188                 int k;
10189                 const msurface_t *surface;
10190                 float surfacecolor4f[4];
10191                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10192                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10193                 vi = 0;
10194                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10195                 {
10196                         surface = texturesurfacelist[texturesurfaceindex];
10197                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10198                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10199                         for (j = 0;j < surface->num_vertices;j++)
10200                         {
10201                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10202                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10203                                 vi++;
10204                         }
10205                 }
10206                 R_Mesh_PrepareVertices_Generic_Unlock();
10207                 RSurf_DrawBatch();
10208         }
10209 }
10210
10211 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10212 {
10213         CHECKGLERROR
10214         RSurf_SetupDepthAndCulling();
10215         if (r_showsurfaces.integer)
10216         {
10217                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10218                 return;
10219         }
10220         switch (vid.renderpath)
10221         {
10222         case RENDERPATH_GL20:
10223         case RENDERPATH_D3D9:
10224         case RENDERPATH_D3D10:
10225         case RENDERPATH_D3D11:
10226         case RENDERPATH_SOFT:
10227         case RENDERPATH_GLES2:
10228                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10229                 break;
10230         case RENDERPATH_GL13:
10231         case RENDERPATH_GLES1:
10232                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10233                 break;
10234         case RENDERPATH_GL11:
10235                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10236                 break;
10237         }
10238         CHECKGLERROR
10239 }
10240
10241 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10242 {
10243         CHECKGLERROR
10244         RSurf_SetupDepthAndCulling();
10245         if (r_showsurfaces.integer)
10246         {
10247                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10248                 return;
10249         }
10250         switch (vid.renderpath)
10251         {
10252         case RENDERPATH_GL20:
10253         case RENDERPATH_D3D9:
10254         case RENDERPATH_D3D10:
10255         case RENDERPATH_D3D11:
10256         case RENDERPATH_SOFT:
10257         case RENDERPATH_GLES2:
10258                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10259                 break;
10260         case RENDERPATH_GL13:
10261         case RENDERPATH_GLES1:
10262                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10263                 break;
10264         case RENDERPATH_GL11:
10265                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10266                 break;
10267         }
10268         CHECKGLERROR
10269 }
10270
10271 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10272 {
10273         int i, j;
10274         int texturenumsurfaces, endsurface;
10275         texture_t *texture;
10276         const msurface_t *surface;
10277         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10278
10279         // if the model is static it doesn't matter what value we give for
10280         // wantnormals and wanttangents, so this logic uses only rules applicable
10281         // to a model, knowing that they are meaningless otherwise
10282         if (ent == r_refdef.scene.worldentity)
10283                 RSurf_ActiveWorldEntity();
10284         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10285                 RSurf_ActiveModelEntity(ent, false, false, false);
10286         else
10287         {
10288                 switch (vid.renderpath)
10289                 {
10290                 case RENDERPATH_GL20:
10291                 case RENDERPATH_D3D9:
10292                 case RENDERPATH_D3D10:
10293                 case RENDERPATH_D3D11:
10294                 case RENDERPATH_SOFT:
10295                 case RENDERPATH_GLES2:
10296                         RSurf_ActiveModelEntity(ent, true, true, false);
10297                         break;
10298                 case RENDERPATH_GL11:
10299                 case RENDERPATH_GL13:
10300                 case RENDERPATH_GLES1:
10301                         RSurf_ActiveModelEntity(ent, true, false, false);
10302                         break;
10303                 }
10304         }
10305
10306         if (r_transparentdepthmasking.integer)
10307         {
10308                 qboolean setup = false;
10309                 for (i = 0;i < numsurfaces;i = j)
10310                 {
10311                         j = i + 1;
10312                         surface = rsurface.modelsurfaces + surfacelist[i];
10313                         texture = surface->texture;
10314                         rsurface.texture = R_GetCurrentTexture(texture);
10315                         rsurface.lightmaptexture = NULL;
10316                         rsurface.deluxemaptexture = NULL;
10317                         rsurface.uselightmaptexture = false;
10318                         // scan ahead until we find a different texture
10319                         endsurface = min(i + 1024, numsurfaces);
10320                         texturenumsurfaces = 0;
10321                         texturesurfacelist[texturenumsurfaces++] = surface;
10322                         for (;j < endsurface;j++)
10323                         {
10324                                 surface = rsurface.modelsurfaces + surfacelist[j];
10325                                 if (texture != surface->texture)
10326                                         break;
10327                                 texturesurfacelist[texturenumsurfaces++] = surface;
10328                         }
10329                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10330                                 continue;
10331                         // render the range of surfaces as depth
10332                         if (!setup)
10333                         {
10334                                 setup = true;
10335                                 GL_ColorMask(0,0,0,0);
10336                                 GL_Color(1,1,1,1);
10337                                 GL_DepthTest(true);
10338                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10339                                 GL_DepthMask(true);
10340 //                              R_Mesh_ResetTextureState();
10341                                 R_SetupShader_DepthOrShadow(false);
10342                         }
10343                         RSurf_SetupDepthAndCulling();
10344                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10345                         if (rsurface.batchvertex3fbuffer)
10346                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10347                         else
10348                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10349                         RSurf_DrawBatch();
10350                 }
10351                 if (setup)
10352                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10353         }
10354
10355         for (i = 0;i < numsurfaces;i = j)
10356         {
10357                 j = i + 1;
10358                 surface = rsurface.modelsurfaces + surfacelist[i];
10359                 texture = surface->texture;
10360                 rsurface.texture = R_GetCurrentTexture(texture);
10361                 // scan ahead until we find a different texture
10362                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10363                 texturenumsurfaces = 0;
10364                 texturesurfacelist[texturenumsurfaces++] = surface;
10365                 if(FAKELIGHT_ENABLED)
10366                 {
10367                         rsurface.lightmaptexture = NULL;
10368                         rsurface.deluxemaptexture = NULL;
10369                         rsurface.uselightmaptexture = false;
10370                         for (;j < endsurface;j++)
10371                         {
10372                                 surface = rsurface.modelsurfaces + surfacelist[j];
10373                                 if (texture != surface->texture)
10374                                         break;
10375                                 texturesurfacelist[texturenumsurfaces++] = surface;
10376                         }
10377                 }
10378                 else
10379                 {
10380                         rsurface.lightmaptexture = surface->lightmaptexture;
10381                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10382                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10383                         for (;j < endsurface;j++)
10384                         {
10385                                 surface = rsurface.modelsurfaces + surfacelist[j];
10386                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10387                                         break;
10388                                 texturesurfacelist[texturenumsurfaces++] = surface;
10389                         }
10390                 }
10391                 // render the range of surfaces
10392                 if (ent == r_refdef.scene.worldentity)
10393                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10394                 else
10395                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10396         }
10397         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10398 }
10399
10400 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10401 {
10402         // transparent surfaces get pushed off into the transparent queue
10403         int surfacelistindex;
10404         const msurface_t *surface;
10405         vec3_t tempcenter, center;
10406         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10407         {
10408                 surface = texturesurfacelist[surfacelistindex];
10409                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10410                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10411                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10412                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10413                 if (queueentity->transparent_offset) // transparent offset
10414                 {
10415                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10416                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10417                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10418                 }
10419                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10420         }
10421 }
10422
10423 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10424 {
10425         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10426                 return;
10427         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10428                 return;
10429         RSurf_SetupDepthAndCulling();
10430         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10431         if (rsurface.batchvertex3fbuffer)
10432                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10433         else
10434                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10435         RSurf_DrawBatch();
10436 }
10437
10438 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10439 {
10440         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10441         CHECKGLERROR
10442         if (depthonly)
10443                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10444         else if (prepass)
10445         {
10446                 if (!rsurface.texture->currentnumlayers)
10447                         return;
10448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10449                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10450                 else
10451                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10452         }
10453         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10454                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10455         else if (!rsurface.texture->currentnumlayers)
10456                 return;
10457         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10458         {
10459                 // in the deferred case, transparent surfaces were queued during prepass
10460                 if (!r_shadow_usingdeferredprepass)
10461                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10462         }
10463         else
10464         {
10465                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10466                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10467         }
10468         CHECKGLERROR
10469 }
10470
10471 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10472 {
10473         int i, j;
10474         texture_t *texture;
10475         R_FrameData_SetMark();
10476         // break the surface list down into batches by texture and use of lightmapping
10477         for (i = 0;i < numsurfaces;i = j)
10478         {
10479                 j = i + 1;
10480                 // texture is the base texture pointer, rsurface.texture is the
10481                 // current frame/skin the texture is directing us to use (for example
10482                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10483                 // use skin 1 instead)
10484                 texture = surfacelist[i]->texture;
10485                 rsurface.texture = R_GetCurrentTexture(texture);
10486                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10487                 {
10488                         // if this texture is not the kind we want, skip ahead to the next one
10489                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10490                                 ;
10491                         continue;
10492                 }
10493                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10494                 {
10495                         rsurface.lightmaptexture = NULL;
10496                         rsurface.deluxemaptexture = NULL;
10497                         rsurface.uselightmaptexture = false;
10498                         // simply scan ahead until we find a different texture or lightmap state
10499                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10500                                 ;
10501                 }
10502                 else
10503                 {
10504                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10505                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10506                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10507                         // simply scan ahead until we find a different texture or lightmap state
10508                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10509                                 ;
10510                 }
10511                 // render the range of surfaces
10512                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10513         }
10514         R_FrameData_ReturnToMark();
10515 }
10516
10517 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10518 {
10519         CHECKGLERROR
10520         if (depthonly)
10521                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10522         else if (prepass)
10523         {
10524                 if (!rsurface.texture->currentnumlayers)
10525                         return;
10526                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10527                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10528                 else
10529                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10530         }
10531         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10532                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10533         else if (!rsurface.texture->currentnumlayers)
10534                 return;
10535         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10536         {
10537                 // in the deferred case, transparent surfaces were queued during prepass
10538                 if (!r_shadow_usingdeferredprepass)
10539                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10540         }
10541         else
10542         {
10543                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10544                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10545         }
10546         CHECKGLERROR
10547 }
10548
10549 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10550 {
10551         int i, j;
10552         texture_t *texture;
10553         R_FrameData_SetMark();
10554         // break the surface list down into batches by texture and use of lightmapping
10555         for (i = 0;i < numsurfaces;i = j)
10556         {
10557                 j = i + 1;
10558                 // texture is the base texture pointer, rsurface.texture is the
10559                 // current frame/skin the texture is directing us to use (for example
10560                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10561                 // use skin 1 instead)
10562                 texture = surfacelist[i]->texture;
10563                 rsurface.texture = R_GetCurrentTexture(texture);
10564                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10565                 {
10566                         // if this texture is not the kind we want, skip ahead to the next one
10567                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10568                                 ;
10569                         continue;
10570                 }
10571                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10572                 {
10573                         rsurface.lightmaptexture = NULL;
10574                         rsurface.deluxemaptexture = NULL;
10575                         rsurface.uselightmaptexture = false;
10576                         // simply scan ahead until we find a different texture or lightmap state
10577                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10578                                 ;
10579                 }
10580                 else
10581                 {
10582                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10583                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10584                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10585                         // simply scan ahead until we find a different texture or lightmap state
10586                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10587                                 ;
10588                 }
10589                 // render the range of surfaces
10590                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10591         }
10592         R_FrameData_ReturnToMark();
10593 }
10594
10595 float locboxvertex3f[6*4*3] =
10596 {
10597         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10598         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10599         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10600         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10601         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10602         1,0,0, 0,0,0, 0,1,0, 1,1,0
10603 };
10604
10605 unsigned short locboxelements[6*2*3] =
10606 {
10607          0, 1, 2, 0, 2, 3,
10608          4, 5, 6, 4, 6, 7,
10609          8, 9,10, 8,10,11,
10610         12,13,14, 12,14,15,
10611         16,17,18, 16,18,19,
10612         20,21,22, 20,22,23
10613 };
10614
10615 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10616 {
10617         int i, j;
10618         cl_locnode_t *loc = (cl_locnode_t *)ent;
10619         vec3_t mins, size;
10620         float vertex3f[6*4*3];
10621         CHECKGLERROR
10622         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10623         GL_DepthMask(false);
10624         GL_DepthRange(0, 1);
10625         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10626         GL_DepthTest(true);
10627         GL_CullFace(GL_NONE);
10628         R_EntityMatrix(&identitymatrix);
10629
10630 //      R_Mesh_ResetTextureState();
10631
10632         i = surfacelist[0];
10633         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10634                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10635                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10636                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10637
10638         if (VectorCompare(loc->mins, loc->maxs))
10639         {
10640                 VectorSet(size, 2, 2, 2);
10641                 VectorMA(loc->mins, -0.5f, size, mins);
10642         }
10643         else
10644         {
10645                 VectorCopy(loc->mins, mins);
10646                 VectorSubtract(loc->maxs, loc->mins, size);
10647         }
10648
10649         for (i = 0;i < 6*4*3;)
10650                 for (j = 0;j < 3;j++, i++)
10651                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10652
10653         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10654         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10655         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10656 }
10657
10658 void R_DrawLocs(void)
10659 {
10660         int index;
10661         cl_locnode_t *loc, *nearestloc;
10662         vec3_t center;
10663         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10664         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10665         {
10666                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10667                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10668         }
10669 }
10670
10671 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10672 {
10673         if (decalsystem->decals)
10674                 Mem_Free(decalsystem->decals);
10675         memset(decalsystem, 0, sizeof(*decalsystem));
10676 }
10677
10678 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)
10679 {
10680         tridecal_t *decal;
10681         tridecal_t *decals;
10682         int i;
10683
10684         // expand or initialize the system
10685         if (decalsystem->maxdecals <= decalsystem->numdecals)
10686         {
10687                 decalsystem_t old = *decalsystem;
10688                 qboolean useshortelements;
10689                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10690                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10691                 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)));
10692                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10693                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10694                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10695                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10696                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10697                 if (decalsystem->numdecals)
10698                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10699                 if (old.decals)
10700                         Mem_Free(old.decals);
10701                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10702                         decalsystem->element3i[i] = i;
10703                 if (useshortelements)
10704                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10705                                 decalsystem->element3s[i] = i;
10706         }
10707
10708         // grab a decal and search for another free slot for the next one
10709         decals = decalsystem->decals;
10710         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10711         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10712                 ;
10713         decalsystem->freedecal = i;
10714         if (decalsystem->numdecals <= i)
10715                 decalsystem->numdecals = i + 1;
10716
10717         // initialize the decal
10718         decal->lived = 0;
10719         decal->triangleindex = triangleindex;
10720         decal->surfaceindex = surfaceindex;
10721         decal->decalsequence = decalsequence;
10722         decal->color4f[0][0] = c0[0];
10723         decal->color4f[0][1] = c0[1];
10724         decal->color4f[0][2] = c0[2];
10725         decal->color4f[0][3] = 1;
10726         decal->color4f[1][0] = c1[0];
10727         decal->color4f[1][1] = c1[1];
10728         decal->color4f[1][2] = c1[2];
10729         decal->color4f[1][3] = 1;
10730         decal->color4f[2][0] = c2[0];
10731         decal->color4f[2][1] = c2[1];
10732         decal->color4f[2][2] = c2[2];
10733         decal->color4f[2][3] = 1;
10734         decal->vertex3f[0][0] = v0[0];
10735         decal->vertex3f[0][1] = v0[1];
10736         decal->vertex3f[0][2] = v0[2];
10737         decal->vertex3f[1][0] = v1[0];
10738         decal->vertex3f[1][1] = v1[1];
10739         decal->vertex3f[1][2] = v1[2];
10740         decal->vertex3f[2][0] = v2[0];
10741         decal->vertex3f[2][1] = v2[1];
10742         decal->vertex3f[2][2] = v2[2];
10743         decal->texcoord2f[0][0] = t0[0];
10744         decal->texcoord2f[0][1] = t0[1];
10745         decal->texcoord2f[1][0] = t1[0];
10746         decal->texcoord2f[1][1] = t1[1];
10747         decal->texcoord2f[2][0] = t2[0];
10748         decal->texcoord2f[2][1] = t2[1];
10749         TriangleNormal(v0, v1, v2, decal->plane);
10750         VectorNormalize(decal->plane);
10751         decal->plane[3] = DotProduct(v0, decal->plane);
10752 }
10753
10754 extern cvar_t cl_decals_bias;
10755 extern cvar_t cl_decals_models;
10756 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10757 // baseparms, parms, temps
10758 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)
10759 {
10760         int cornerindex;
10761         int index;
10762         float v[9][3];
10763         const float *vertex3f;
10764         const float *normal3f;
10765         int numpoints;
10766         float points[2][9][3];
10767         float temp[3];
10768         float tc[9][2];
10769         float f;
10770         float c[9][4];
10771         const int *e;
10772
10773         e = rsurface.modelelement3i + 3*triangleindex;
10774
10775         vertex3f = rsurface.modelvertex3f;
10776         normal3f = rsurface.modelnormal3f;
10777
10778         if (normal3f)
10779         {
10780                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10781                 {
10782                         index = 3*e[cornerindex];
10783                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10784                 }
10785         }
10786         else
10787         {
10788                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10789                 {
10790                         index = 3*e[cornerindex];
10791                         VectorCopy(vertex3f + index, v[cornerindex]);
10792                 }
10793         }
10794
10795         // cull backfaces
10796         //TriangleNormal(v[0], v[1], v[2], normal);
10797         //if (DotProduct(normal, localnormal) < 0.0f)
10798         //      continue;
10799         // clip by each of the box planes formed from the projection matrix
10800         // if anything survives, we emit the decal
10801         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]);
10802         if (numpoints < 3)
10803                 return;
10804         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]);
10805         if (numpoints < 3)
10806                 return;
10807         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]);
10808         if (numpoints < 3)
10809                 return;
10810         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]);
10811         if (numpoints < 3)
10812                 return;
10813         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]);
10814         if (numpoints < 3)
10815                 return;
10816         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]);
10817         if (numpoints < 3)
10818                 return;
10819         // some part of the triangle survived, so we have to accept it...
10820         if (dynamic)
10821         {
10822                 // dynamic always uses the original triangle
10823                 numpoints = 3;
10824                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10825                 {
10826                         index = 3*e[cornerindex];
10827                         VectorCopy(vertex3f + index, v[cornerindex]);
10828                 }
10829         }
10830         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10831         {
10832                 // convert vertex positions to texcoords
10833                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10834                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10835                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10836                 // calculate distance fade from the projection origin
10837                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10838                 f = bound(0.0f, f, 1.0f);
10839                 c[cornerindex][0] = r * f;
10840                 c[cornerindex][1] = g * f;
10841                 c[cornerindex][2] = b * f;
10842                 c[cornerindex][3] = 1.0f;
10843                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10844         }
10845         if (dynamic)
10846                 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);
10847         else
10848                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10849                         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);
10850 }
10851 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)
10852 {
10853         matrix4x4_t projection;
10854         decalsystem_t *decalsystem;
10855         qboolean dynamic;
10856         dp_model_t *model;
10857         const msurface_t *surface;
10858         const msurface_t *surfaces;
10859         const int *surfacelist;
10860         const texture_t *texture;
10861         int numtriangles;
10862         int numsurfacelist;
10863         int surfacelistindex;
10864         int surfaceindex;
10865         int triangleindex;
10866         float localorigin[3];
10867         float localnormal[3];
10868         float localmins[3];
10869         float localmaxs[3];
10870         float localsize;
10871         //float normal[3];
10872         float planes[6][4];
10873         float angles[3];
10874         bih_t *bih;
10875         int bih_triangles_count;
10876         int bih_triangles[256];
10877         int bih_surfaces[256];
10878
10879         decalsystem = &ent->decalsystem;
10880         model = ent->model;
10881         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10882         {
10883                 R_DecalSystem_Reset(&ent->decalsystem);
10884                 return;
10885         }
10886
10887         if (!model->brush.data_leafs && !cl_decals_models.integer)
10888         {
10889                 if (decalsystem->model)
10890                         R_DecalSystem_Reset(decalsystem);
10891                 return;
10892         }
10893
10894         if (decalsystem->model != model)
10895                 R_DecalSystem_Reset(decalsystem);
10896         decalsystem->model = model;
10897
10898         RSurf_ActiveModelEntity(ent, true, false, false);
10899
10900         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10901         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10902         VectorNormalize(localnormal);
10903         localsize = worldsize*rsurface.inversematrixscale;
10904         localmins[0] = localorigin[0] - localsize;
10905         localmins[1] = localorigin[1] - localsize;
10906         localmins[2] = localorigin[2] - localsize;
10907         localmaxs[0] = localorigin[0] + localsize;
10908         localmaxs[1] = localorigin[1] + localsize;
10909         localmaxs[2] = localorigin[2] + localsize;
10910
10911         //VectorCopy(localnormal, planes[4]);
10912         //VectorVectors(planes[4], planes[2], planes[0]);
10913         AnglesFromVectors(angles, localnormal, NULL, false);
10914         AngleVectors(angles, planes[0], planes[2], planes[4]);
10915         VectorNegate(planes[0], planes[1]);
10916         VectorNegate(planes[2], planes[3]);
10917         VectorNegate(planes[4], planes[5]);
10918         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10919         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10920         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10921         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10922         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10923         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10924
10925 #if 1
10926 // works
10927 {
10928         matrix4x4_t forwardprojection;
10929         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10930         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10931 }
10932 #else
10933 // broken
10934 {
10935         float projectionvector[4][3];
10936         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10937         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10938         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10939         projectionvector[0][0] = planes[0][0] * ilocalsize;
10940         projectionvector[0][1] = planes[1][0] * ilocalsize;
10941         projectionvector[0][2] = planes[2][0] * ilocalsize;
10942         projectionvector[1][0] = planes[0][1] * ilocalsize;
10943         projectionvector[1][1] = planes[1][1] * ilocalsize;
10944         projectionvector[1][2] = planes[2][1] * ilocalsize;
10945         projectionvector[2][0] = planes[0][2] * ilocalsize;
10946         projectionvector[2][1] = planes[1][2] * ilocalsize;
10947         projectionvector[2][2] = planes[2][2] * ilocalsize;
10948         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10949         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10950         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10951         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10952 }
10953 #endif
10954
10955         dynamic = model->surfmesh.isanimated;
10956         numsurfacelist = model->nummodelsurfaces;
10957         surfacelist = model->sortedmodelsurfaces;
10958         surfaces = model->data_surfaces;
10959
10960         bih = NULL;
10961         bih_triangles_count = -1;
10962         if(!dynamic)
10963         {
10964                 if(model->render_bih.numleafs)
10965                         bih = &model->render_bih;
10966                 else if(model->collision_bih.numleafs)
10967                         bih = &model->collision_bih;
10968         }
10969         if(bih)
10970                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10971         if(bih_triangles_count == 0)
10972                 return;
10973         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10974                 return;
10975         if(bih_triangles_count > 0)
10976         {
10977                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10978                 {
10979                         surfaceindex = bih_surfaces[triangleindex];
10980                         surface = surfaces + surfaceindex;
10981                         texture = surface->texture;
10982                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10983                                 continue;
10984                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10985                                 continue;
10986                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10987                 }
10988         }
10989         else
10990         {
10991                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10992                 {
10993                         surfaceindex = surfacelist[surfacelistindex];
10994                         surface = surfaces + surfaceindex;
10995                         // check cull box first because it rejects more than any other check
10996                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10997                                 continue;
10998                         // skip transparent surfaces
10999                         texture = surface->texture;
11000                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11001                                 continue;
11002                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11003                                 continue;
11004                         numtriangles = surface->num_triangles;
11005                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11006                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11007                 }
11008         }
11009 }
11010
11011 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11012 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)
11013 {
11014         int renderentityindex;
11015         float worldmins[3];
11016         float worldmaxs[3];
11017         entity_render_t *ent;
11018
11019         if (!cl_decals_newsystem.integer)
11020                 return;
11021
11022         worldmins[0] = worldorigin[0] - worldsize;
11023         worldmins[1] = worldorigin[1] - worldsize;
11024         worldmins[2] = worldorigin[2] - worldsize;
11025         worldmaxs[0] = worldorigin[0] + worldsize;
11026         worldmaxs[1] = worldorigin[1] + worldsize;
11027         worldmaxs[2] = worldorigin[2] + worldsize;
11028
11029         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11030
11031         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11032         {
11033                 ent = r_refdef.scene.entities[renderentityindex];
11034                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11035                         continue;
11036
11037                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11038         }
11039 }
11040
11041 typedef struct r_decalsystem_splatqueue_s
11042 {
11043         vec3_t worldorigin;
11044         vec3_t worldnormal;
11045         float color[4];
11046         float tcrange[4];
11047         float worldsize;
11048         int decalsequence;
11049 }
11050 r_decalsystem_splatqueue_t;
11051
11052 int r_decalsystem_numqueued = 0;
11053 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11054
11055 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)
11056 {
11057         r_decalsystem_splatqueue_t *queue;
11058
11059         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11060                 return;
11061
11062         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11063         VectorCopy(worldorigin, queue->worldorigin);
11064         VectorCopy(worldnormal, queue->worldnormal);
11065         Vector4Set(queue->color, r, g, b, a);
11066         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11067         queue->worldsize = worldsize;
11068         queue->decalsequence = cl.decalsequence++;
11069 }
11070
11071 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11072 {
11073         int i;
11074         r_decalsystem_splatqueue_t *queue;
11075
11076         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11077                 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);
11078         r_decalsystem_numqueued = 0;
11079 }
11080
11081 extern cvar_t cl_decals_max;
11082 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11083 {
11084         int i;
11085         decalsystem_t *decalsystem = &ent->decalsystem;
11086         int numdecals;
11087         int killsequence;
11088         tridecal_t *decal;
11089         float frametime;
11090         float lifetime;
11091
11092         if (!decalsystem->numdecals)
11093                 return;
11094
11095         if (r_showsurfaces.integer)
11096                 return;
11097
11098         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11099         {
11100                 R_DecalSystem_Reset(decalsystem);
11101                 return;
11102         }
11103
11104         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11105         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11106
11107         if (decalsystem->lastupdatetime)
11108                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11109         else
11110                 frametime = 0;
11111         decalsystem->lastupdatetime = r_refdef.scene.time;
11112         decal = decalsystem->decals;
11113         numdecals = decalsystem->numdecals;
11114
11115         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11116         {
11117                 if (decal->color4f[0][3])
11118                 {
11119                         decal->lived += frametime;
11120                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11121                         {
11122                                 memset(decal, 0, sizeof(*decal));
11123                                 if (decalsystem->freedecal > i)
11124                                         decalsystem->freedecal = i;
11125                         }
11126                 }
11127         }
11128         decal = decalsystem->decals;
11129         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11130                 numdecals--;
11131
11132         // collapse the array by shuffling the tail decals into the gaps
11133         for (;;)
11134         {
11135                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11136                         decalsystem->freedecal++;
11137                 if (decalsystem->freedecal == numdecals)
11138                         break;
11139                 decal[decalsystem->freedecal] = decal[--numdecals];
11140         }
11141
11142         decalsystem->numdecals = numdecals;
11143
11144         if (numdecals <= 0)
11145         {
11146                 // if there are no decals left, reset decalsystem
11147                 R_DecalSystem_Reset(decalsystem);
11148         }
11149 }
11150
11151 extern skinframe_t *decalskinframe;
11152 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11153 {
11154         int i;
11155         decalsystem_t *decalsystem = &ent->decalsystem;
11156         int numdecals;
11157         tridecal_t *decal;
11158         float faderate;
11159         float alpha;
11160         float *v3f;
11161         float *c4f;
11162         float *t2f;
11163         const int *e;
11164         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11165         int numtris = 0;
11166
11167         numdecals = decalsystem->numdecals;
11168         if (!numdecals)
11169                 return;
11170
11171         if (r_showsurfaces.integer)
11172                 return;
11173
11174         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11175         {
11176                 R_DecalSystem_Reset(decalsystem);
11177                 return;
11178         }
11179
11180         // if the model is static it doesn't matter what value we give for
11181         // wantnormals and wanttangents, so this logic uses only rules applicable
11182         // to a model, knowing that they are meaningless otherwise
11183         if (ent == r_refdef.scene.worldentity)
11184                 RSurf_ActiveWorldEntity();
11185         else
11186                 RSurf_ActiveModelEntity(ent, false, false, false);
11187
11188         decalsystem->lastupdatetime = r_refdef.scene.time;
11189         decal = decalsystem->decals;
11190
11191         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11192
11193         // update vertex positions for animated models
11194         v3f = decalsystem->vertex3f;
11195         c4f = decalsystem->color4f;
11196         t2f = decalsystem->texcoord2f;
11197         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11198         {
11199                 if (!decal->color4f[0][3])
11200                         continue;
11201
11202                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11203                         continue;
11204
11205                 // skip backfaces
11206                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11207                         continue;
11208
11209                 // update color values for fading decals
11210                 if (decal->lived >= cl_decals_time.value)
11211                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11212                 else
11213                         alpha = 1.0f;
11214
11215                 c4f[ 0] = decal->color4f[0][0] * alpha;
11216                 c4f[ 1] = decal->color4f[0][1] * alpha;
11217                 c4f[ 2] = decal->color4f[0][2] * alpha;
11218                 c4f[ 3] = 1;
11219                 c4f[ 4] = decal->color4f[1][0] * alpha;
11220                 c4f[ 5] = decal->color4f[1][1] * alpha;
11221                 c4f[ 6] = decal->color4f[1][2] * alpha;
11222                 c4f[ 7] = 1;
11223                 c4f[ 8] = decal->color4f[2][0] * alpha;
11224                 c4f[ 9] = decal->color4f[2][1] * alpha;
11225                 c4f[10] = decal->color4f[2][2] * alpha;
11226                 c4f[11] = 1;
11227
11228                 t2f[0] = decal->texcoord2f[0][0];
11229                 t2f[1] = decal->texcoord2f[0][1];
11230                 t2f[2] = decal->texcoord2f[1][0];
11231                 t2f[3] = decal->texcoord2f[1][1];
11232                 t2f[4] = decal->texcoord2f[2][0];
11233                 t2f[5] = decal->texcoord2f[2][1];
11234
11235                 // update vertex positions for animated models
11236                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11237                 {
11238                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11239                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11240                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11241                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11242                 }
11243                 else
11244                 {
11245                         VectorCopy(decal->vertex3f[0], v3f);
11246                         VectorCopy(decal->vertex3f[1], v3f + 3);
11247                         VectorCopy(decal->vertex3f[2], v3f + 6);
11248                 }
11249
11250                 if (r_refdef.fogenabled)
11251                 {
11252                         alpha = RSurf_FogVertex(v3f);
11253                         VectorScale(c4f, alpha, c4f);
11254                         alpha = RSurf_FogVertex(v3f + 3);
11255                         VectorScale(c4f + 4, alpha, c4f + 4);
11256                         alpha = RSurf_FogVertex(v3f + 6);
11257                         VectorScale(c4f + 8, alpha, c4f + 8);
11258                 }
11259
11260                 v3f += 9;
11261                 c4f += 12;
11262                 t2f += 6;
11263                 numtris++;
11264         }
11265
11266         if (numtris > 0)
11267         {
11268                 r_refdef.stats.drawndecals += numtris;
11269
11270                 // now render the decals all at once
11271                 // (this assumes they all use one particle font texture!)
11272                 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);
11273 //              R_Mesh_ResetTextureState();
11274                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11275                 GL_DepthMask(false);
11276                 GL_DepthRange(0, 1);
11277                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11278                 GL_DepthTest(true);
11279                 GL_CullFace(GL_NONE);
11280                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11281                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11282                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11283         }
11284 }
11285
11286 static void R_DrawModelDecals(void)
11287 {
11288         int i, numdecals;
11289
11290         // fade faster when there are too many decals
11291         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11292         for (i = 0;i < r_refdef.scene.numentities;i++)
11293                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11294
11295         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11296         for (i = 0;i < r_refdef.scene.numentities;i++)
11297                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11298                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11299
11300         R_DecalSystem_ApplySplatEntitiesQueue();
11301
11302         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11303         for (i = 0;i < r_refdef.scene.numentities;i++)
11304                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11305
11306         r_refdef.stats.totaldecals += numdecals;
11307
11308         if (r_showsurfaces.integer)
11309                 return;
11310
11311         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11312
11313         for (i = 0;i < r_refdef.scene.numentities;i++)
11314         {
11315                 if (!r_refdef.viewcache.entityvisible[i])
11316                         continue;
11317                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11318                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11319         }
11320 }
11321
11322 extern cvar_t mod_collision_bih;
11323 void R_DrawDebugModel(void)
11324 {
11325         entity_render_t *ent = rsurface.entity;
11326         int i, j, k, l, flagsmask;
11327         const msurface_t *surface;
11328         dp_model_t *model = ent->model;
11329         vec3_t v;
11330
11331         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11332                 return;
11333
11334         if (r_showoverdraw.value > 0)
11335         {
11336                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11337                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11338                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11339                 GL_DepthTest(false);
11340                 GL_DepthMask(false);
11341                 GL_DepthRange(0, 1);
11342                 GL_BlendFunc(GL_ONE, GL_ONE);
11343                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11344                 {
11345                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11346                                 continue;
11347                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11348                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11349                         {
11350                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11351                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11352                                 if (!rsurface.texture->currentlayers->depthmask)
11353                                         GL_Color(c, 0, 0, 1.0f);
11354                                 else if (ent == r_refdef.scene.worldentity)
11355                                         GL_Color(c, c, c, 1.0f);
11356                                 else
11357                                         GL_Color(0, c, 0, 1.0f);
11358                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11359                                 RSurf_DrawBatch();
11360                         }
11361                 }
11362                 rsurface.texture = NULL;
11363         }
11364
11365         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11366
11367 //      R_Mesh_ResetTextureState();
11368         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11369         GL_DepthRange(0, 1);
11370         GL_DepthTest(!r_showdisabledepthtest.integer);
11371         GL_DepthMask(false);
11372         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11373
11374         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11375         {
11376                 int triangleindex;
11377                 int bihleafindex;
11378                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11379                 const q3mbrush_t *brush;
11380                 const bih_t *bih = &model->collision_bih;
11381                 const bih_leaf_t *bihleaf;
11382                 float vertex3f[3][3];
11383                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11384                 cullbox = false;
11385                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11386                 {
11387                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11388                                 continue;
11389                         switch (bihleaf->type)
11390                         {
11391                         case BIH_BRUSH:
11392                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11393                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11394                                 {
11395                                         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);
11396                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11397                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11398                                 }
11399                                 break;
11400                         case BIH_COLLISIONTRIANGLE:
11401                                 triangleindex = bihleaf->itemindex;
11402                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11403                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11404                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11405                                 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);
11406                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11407                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11408                                 break;
11409                         case BIH_RENDERTRIANGLE:
11410                                 triangleindex = bihleaf->itemindex;
11411                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11412                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11413                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11414                                 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);
11415                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11416                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11417                                 break;
11418                         }
11419                 }
11420         }
11421
11422         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11423
11424 #ifndef USE_GLES2
11425         if (r_showtris.integer && qglPolygonMode)
11426         {
11427                 if (r_showdisabledepthtest.integer)
11428                 {
11429                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11430                         GL_DepthMask(false);
11431                 }
11432                 else
11433                 {
11434                         GL_BlendFunc(GL_ONE, GL_ZERO);
11435                         GL_DepthMask(true);
11436                 }
11437                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11438                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11439                 {
11440                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11441                                 continue;
11442                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11443                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11444                         {
11445                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11446                                 if (!rsurface.texture->currentlayers->depthmask)
11447                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11448                                 else if (ent == r_refdef.scene.worldentity)
11449                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11450                                 else
11451                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11452                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11453                                 RSurf_DrawBatch();
11454                         }
11455                 }
11456                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11457                 rsurface.texture = NULL;
11458         }
11459
11460         if (r_shownormals.value != 0 && qglBegin)
11461         {
11462                 if (r_showdisabledepthtest.integer)
11463                 {
11464                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11465                         GL_DepthMask(false);
11466                 }
11467                 else
11468                 {
11469                         GL_BlendFunc(GL_ONE, GL_ZERO);
11470                         GL_DepthMask(true);
11471                 }
11472                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11473                 {
11474                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11475                                 continue;
11476                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11477                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11478                         {
11479                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11480                                 qglBegin(GL_LINES);
11481                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11482                                 {
11483                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11484                                         {
11485                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11486                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11487                                                 qglVertex3f(v[0], v[1], v[2]);
11488                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11489                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11490                                                 qglVertex3f(v[0], v[1], v[2]);
11491                                         }
11492                                 }
11493                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11494                                 {
11495                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11496                                         {
11497                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11498                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11499                                                 qglVertex3f(v[0], v[1], v[2]);
11500                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11501                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11502                                                 qglVertex3f(v[0], v[1], v[2]);
11503                                         }
11504                                 }
11505                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11506                                 {
11507                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11508                                         {
11509                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11510                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11511                                                 qglVertex3f(v[0], v[1], v[2]);
11512                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11513                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11514                                                 qglVertex3f(v[0], v[1], v[2]);
11515                                         }
11516                                 }
11517                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11518                                 {
11519                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11520                                         {
11521                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11522                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11523                                                 qglVertex3f(v[0], v[1], v[2]);
11524                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11525                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11526                                                 qglVertex3f(v[0], v[1], v[2]);
11527                                         }
11528                                 }
11529                                 qglEnd();
11530                                 CHECKGLERROR
11531                         }
11532                 }
11533                 rsurface.texture = NULL;
11534         }
11535 #endif
11536 }
11537
11538 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11539 int r_maxsurfacelist = 0;
11540 const msurface_t **r_surfacelist = NULL;
11541 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11542 {
11543         int i, j, endj, flagsmask;
11544         dp_model_t *model = r_refdef.scene.worldmodel;
11545         msurface_t *surfaces;
11546         unsigned char *update;
11547         int numsurfacelist = 0;
11548         if (model == NULL)
11549                 return;
11550
11551         if (r_maxsurfacelist < model->num_surfaces)
11552         {
11553                 r_maxsurfacelist = model->num_surfaces;
11554                 if (r_surfacelist)
11555                         Mem_Free((msurface_t**)r_surfacelist);
11556                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11557         }
11558
11559         RSurf_ActiveWorldEntity();
11560
11561         surfaces = model->data_surfaces;
11562         update = model->brushq1.lightmapupdateflags;
11563
11564         // update light styles on this submodel
11565         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11566         {
11567                 model_brush_lightstyleinfo_t *style;
11568                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11569                 {
11570                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11571                         {
11572                                 int *list = style->surfacelist;
11573                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11574                                 for (j = 0;j < style->numsurfaces;j++)
11575                                         update[list[j]] = true;
11576                         }
11577                 }
11578         }
11579
11580         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11581
11582         if (debug)
11583         {
11584                 R_DrawDebugModel();
11585                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11586                 return;
11587         }
11588
11589         rsurface.lightmaptexture = NULL;
11590         rsurface.deluxemaptexture = NULL;
11591         rsurface.uselightmaptexture = false;
11592         rsurface.texture = NULL;
11593         rsurface.rtlight = NULL;
11594         numsurfacelist = 0;
11595         // add visible surfaces to draw list
11596         for (i = 0;i < model->nummodelsurfaces;i++)
11597         {
11598                 j = model->sortedmodelsurfaces[i];
11599                 if (r_refdef.viewcache.world_surfacevisible[j])
11600                         r_surfacelist[numsurfacelist++] = surfaces + j;
11601         }
11602         // update lightmaps if needed
11603         if (model->brushq1.firstrender)
11604         {
11605                 model->brushq1.firstrender = false;
11606                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11607                         if (update[j])
11608                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11609         }
11610         else if (update)
11611         {
11612                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11613                         if (r_refdef.viewcache.world_surfacevisible[j])
11614                                 if (update[j])
11615                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11616         }
11617         // don't do anything if there were no surfaces
11618         if (!numsurfacelist)
11619         {
11620                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11621                 return;
11622         }
11623         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11624
11625         // add to stats if desired
11626         if (r_speeds.integer && !skysurfaces && !depthonly)
11627         {
11628                 r_refdef.stats.world_surfaces += numsurfacelist;
11629                 for (j = 0;j < numsurfacelist;j++)
11630                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11631         }
11632
11633         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11634 }
11635
11636 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11637 {
11638         int i, j, endj, flagsmask;
11639         dp_model_t *model = ent->model;
11640         msurface_t *surfaces;
11641         unsigned char *update;
11642         int numsurfacelist = 0;
11643         if (model == NULL)
11644                 return;
11645
11646         if (r_maxsurfacelist < model->num_surfaces)
11647         {
11648                 r_maxsurfacelist = model->num_surfaces;
11649                 if (r_surfacelist)
11650                         Mem_Free((msurface_t **)r_surfacelist);
11651                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11652         }
11653
11654         // if the model is static it doesn't matter what value we give for
11655         // wantnormals and wanttangents, so this logic uses only rules applicable
11656         // to a model, knowing that they are meaningless otherwise
11657         if (ent == r_refdef.scene.worldentity)
11658                 RSurf_ActiveWorldEntity();
11659         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11660                 RSurf_ActiveModelEntity(ent, false, false, false);
11661         else if (prepass)
11662                 RSurf_ActiveModelEntity(ent, true, true, true);
11663         else if (depthonly)
11664         {
11665                 switch (vid.renderpath)
11666                 {
11667                 case RENDERPATH_GL20:
11668                 case RENDERPATH_D3D9:
11669                 case RENDERPATH_D3D10:
11670                 case RENDERPATH_D3D11:
11671                 case RENDERPATH_SOFT:
11672                 case RENDERPATH_GLES2:
11673                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11674                         break;
11675                 case RENDERPATH_GL11:
11676                 case RENDERPATH_GL13:
11677                 case RENDERPATH_GLES1:
11678                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11679                         break;
11680                 }
11681         }
11682         else
11683         {
11684                 switch (vid.renderpath)
11685                 {
11686                 case RENDERPATH_GL20:
11687                 case RENDERPATH_D3D9:
11688                 case RENDERPATH_D3D10:
11689                 case RENDERPATH_D3D11:
11690                 case RENDERPATH_SOFT:
11691                 case RENDERPATH_GLES2:
11692                         RSurf_ActiveModelEntity(ent, true, true, false);
11693                         break;
11694                 case RENDERPATH_GL11:
11695                 case RENDERPATH_GL13:
11696                 case RENDERPATH_GLES1:
11697                         RSurf_ActiveModelEntity(ent, true, false, false);
11698                         break;
11699                 }
11700         }
11701
11702         surfaces = model->data_surfaces;
11703         update = model->brushq1.lightmapupdateflags;
11704
11705         // update light styles
11706         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11707         {
11708                 model_brush_lightstyleinfo_t *style;
11709                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11710                 {
11711                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11712                         {
11713                                 int *list = style->surfacelist;
11714                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11715                                 for (j = 0;j < style->numsurfaces;j++)
11716                                         update[list[j]] = true;
11717                         }
11718                 }
11719         }
11720
11721         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11722
11723         if (debug)
11724         {
11725                 R_DrawDebugModel();
11726                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11727                 return;
11728         }
11729
11730         rsurface.lightmaptexture = NULL;
11731         rsurface.deluxemaptexture = NULL;
11732         rsurface.uselightmaptexture = false;
11733         rsurface.texture = NULL;
11734         rsurface.rtlight = NULL;
11735         numsurfacelist = 0;
11736         // add visible surfaces to draw list
11737         for (i = 0;i < model->nummodelsurfaces;i++)
11738                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11739         // don't do anything if there were no surfaces
11740         if (!numsurfacelist)
11741         {
11742                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11743                 return;
11744         }
11745         // update lightmaps if needed
11746         if (update)
11747         {
11748                 int updated = 0;
11749                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11750                 {
11751                         if (update[j])
11752                         {
11753                                 updated++;
11754                                 R_BuildLightMap(ent, surfaces + j);
11755                         }
11756                 }
11757         }
11758         if (update)
11759                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11760                         if (update[j])
11761                                 R_BuildLightMap(ent, surfaces + j);
11762         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11763
11764         // add to stats if desired
11765         if (r_speeds.integer && !skysurfaces && !depthonly)
11766         {
11767                 r_refdef.stats.entities_surfaces += numsurfacelist;
11768                 for (j = 0;j < numsurfacelist;j++)
11769                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11770         }
11771
11772         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11773 }
11774
11775 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11776 {
11777         static texture_t texture;
11778         static msurface_t surface;
11779         const msurface_t *surfacelist = &surface;
11780
11781         // fake enough texture and surface state to render this geometry
11782
11783         texture.update_lastrenderframe = -1; // regenerate this texture
11784         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11785         texture.currentskinframe = skinframe;
11786         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11787         texture.offsetmapping = OFFSETMAPPING_OFF;
11788         texture.offsetscale = 1;
11789         texture.specularscalemod = 1;
11790         texture.specularpowermod = 1;
11791
11792         surface.texture = &texture;
11793         surface.num_triangles = numtriangles;
11794         surface.num_firsttriangle = firsttriangle;
11795         surface.num_vertices = numvertices;
11796         surface.num_firstvertex = firstvertex;
11797
11798         // now render it
11799         rsurface.texture = R_GetCurrentTexture(surface.texture);
11800         rsurface.lightmaptexture = NULL;
11801         rsurface.deluxemaptexture = NULL;
11802         rsurface.uselightmaptexture = false;
11803         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11804 }
11805
11806 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)
11807 {
11808         static msurface_t surface;
11809         const msurface_t *surfacelist = &surface;
11810
11811         // fake enough texture and surface state to render this geometry
11812         surface.texture = texture;
11813         surface.num_triangles = numtriangles;
11814         surface.num_firsttriangle = firsttriangle;
11815         surface.num_vertices = numvertices;
11816         surface.num_firstvertex = firstvertex;
11817
11818         // now render it
11819         rsurface.texture = R_GetCurrentTexture(surface.texture);
11820         rsurface.lightmaptexture = NULL;
11821         rsurface.deluxemaptexture = NULL;
11822         rsurface.uselightmaptexture = false;
11823         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11824 }