]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix an obvious crash in user controlled wave func handling
[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_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
104
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
108
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 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."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 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."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 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"};
122 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"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 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"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
131
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
140
141 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)"};
142 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"};
143
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147
148 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"};
149 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"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 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"};
153 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)"};
154 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)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156
157 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)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 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)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173
174 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)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 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"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 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"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
206
207 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"};
208
209 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"};
210
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
214
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 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"};
217
218 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."};
219
220 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)"};
221
222 extern cvar_t v_glslgamma;
223 extern cvar_t v_glslgamma_2d;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679         {"#define USETRIPPY\n", " trippy"},
680 };
681
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
717         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenDepth;
764         int tex_Texture_ScreenNormalMap;
765         int tex_Texture_ScreenDiffuse;
766         int tex_Texture_ScreenSpecular;
767         int tex_Texture_ReflectMask;
768         int tex_Texture_ReflectCube;
769         int tex_Texture_BounceGrid;
770         /// locations of detected uniforms in program object, or -1 if not found
771         int loc_Texture_First;
772         int loc_Texture_Second;
773         int loc_Texture_GammaRamps;
774         int loc_Texture_Normal;
775         int loc_Texture_Color;
776         int loc_Texture_Gloss;
777         int loc_Texture_Glow;
778         int loc_Texture_SecondaryNormal;
779         int loc_Texture_SecondaryColor;
780         int loc_Texture_SecondaryGloss;
781         int loc_Texture_SecondaryGlow;
782         int loc_Texture_Pants;
783         int loc_Texture_Shirt;
784         int loc_Texture_FogHeightTexture;
785         int loc_Texture_FogMask;
786         int loc_Texture_Lightmap;
787         int loc_Texture_Deluxemap;
788         int loc_Texture_Attenuation;
789         int loc_Texture_Cube;
790         int loc_Texture_Refraction;
791         int loc_Texture_Reflection;
792         int loc_Texture_ShadowMap2D;
793         int loc_Texture_CubeProjection;
794         int loc_Texture_ScreenDepth;
795         int loc_Texture_ScreenNormalMap;
796         int loc_Texture_ScreenDiffuse;
797         int loc_Texture_ScreenSpecular;
798         int loc_Texture_ReflectMask;
799         int loc_Texture_ReflectCube;
800         int loc_Texture_BounceGrid;
801         int loc_Alpha;
802         int loc_BloomBlur_Parameters;
803         int loc_ClientTime;
804         int loc_Color_Ambient;
805         int loc_Color_Diffuse;
806         int loc_Color_Specular;
807         int loc_Color_Glow;
808         int loc_Color_Pants;
809         int loc_Color_Shirt;
810         int loc_DeferredColor_Ambient;
811         int loc_DeferredColor_Diffuse;
812         int loc_DeferredColor_Specular;
813         int loc_DeferredMod_Diffuse;
814         int loc_DeferredMod_Specular;
815         int loc_DistortScaleRefractReflect;
816         int loc_EyePosition;
817         int loc_FogColor;
818         int loc_FogHeightFade;
819         int loc_FogPlane;
820         int loc_FogPlaneViewDist;
821         int loc_FogRangeRecip;
822         int loc_LightColor;
823         int loc_LightDir;
824         int loc_LightPosition;
825         int loc_OffsetMapping_ScaleSteps;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_UserVec1;
839         int loc_UserVec2;
840         int loc_UserVec3;
841         int loc_UserVec4;
842         int loc_ViewTintColor;
843         int loc_ViewToLight;
844         int loc_ModelToLight;
845         int loc_TexMatrix;
846         int loc_BackgroundTexMatrix;
847         int loc_ModelViewProjectionMatrix;
848         int loc_ModelViewMatrix;
849         int loc_PixelToScreenTexCoord;
850         int loc_ModelToReflectCube;
851         int loc_ShadowMapMatrix;
852         int loc_BloomColorSubtract;
853         int loc_NormalmapScrollBlend;
854         int loc_BounceGridMatrix;
855         int loc_BounceGridIntensity;
856 }
857 r_glsl_permutation_t;
858
859 #define SHADERPERMUTATION_HASHSIZE 256
860
861
862 // non-degradable "lightweight" shader parameters to keep the permutations simpler
863 // these can NOT degrade! only use for simple stuff
864 enum
865 {
866         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
867         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
868         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
869         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
872         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
873 };
874 #define SHADERSTATICPARMS_COUNT 7
875
876 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
877 static int shaderstaticparms_count = 0;
878
879 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
880 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
881 qboolean R_CompileShader_CheckStaticParms(void)
882 {
883         static int r_compileshader_staticparms_save[1];
884         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
885         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
886
887         // detect all
888         if (r_glsl_saturation_redcompensate.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
890         if (r_glsl_vertextextureblend_usebothalphas.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
892         if (r_shadow_glossexact.integer)
893                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
894         if (r_glsl_postprocess.integer)
895         {
896                 if (r_glsl_postprocess_uservec1_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
898                 if (r_glsl_postprocess_uservec2_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
900                 if (r_glsl_postprocess_uservec3_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
902                 if (r_glsl_postprocess_uservec4_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904         }
905         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
906 }
907
908 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
909         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
910                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
911         else \
912                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
913 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
914 {
915         shaderstaticparms_count = 0;
916
917         // emit all
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
925 }
926
927 /// information about each possible shader permutation
928 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
929 /// currently selected permutation
930 r_glsl_permutation_t *r_glsl_permutation;
931 /// storage for permutations linked in the hash table
932 memexpandablearray_t r_glsl_permutationarray;
933
934 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 {
936         //unsigned int hashdepth = 0;
937         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
938         r_glsl_permutation_t *p;
939         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940         {
941                 if (p->mode == mode && p->permutation == permutation)
942                 {
943                         //if (hashdepth > 10)
944                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945                         return p;
946                 }
947                 //hashdepth++;
948         }
949         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950         p->mode = mode;
951         p->permutation = permutation;
952         p->hashnext = r_glsl_permutationhash[mode][hashindex];
953         r_glsl_permutationhash[mode][hashindex] = p;
954         //if (hashdepth > 10)
955         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956         return p;
957 }
958
959 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 {
961         char *shaderstring;
962         if (!filename || !filename[0])
963                 return NULL;
964         if (!strcmp(filename, "glsl/default.glsl"))
965         {
966                 if (!glslshaderstring)
967                 {
968                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969                         if (glslshaderstring)
970                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
971                         else
972                                 glslshaderstring = (char *)builtinshaderstring;
973                 }
974                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
975                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976                 return shaderstring;
977         }
978         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979         if (shaderstring)
980         {
981                 if (printfromdisknotice)
982                         Con_DPrintf("from disk %s... ", filename);
983                 return shaderstring;
984         }
985         return shaderstring;
986 }
987
988 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 {
990         int i;
991         int sampler;
992         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
993         char *vertexstring, *geometrystring, *fragmentstring;
994         char permutationname[256];
995         int vertstrings_count = 0;
996         int geomstrings_count = 0;
997         int fragstrings_count = 0;
998         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001
1002         if (p->compiled)
1003                 return;
1004         p->compiled = true;
1005         p->program = 0;
1006
1007         permutationname[0] = 0;
1008         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1009         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1010         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011
1012         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013
1014         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1015         if(vid.support.gl20shaders130)
1016         {
1017                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1018                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1019                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1020                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1021                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1022                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023         }
1024
1025         // the first pretext is which type of shader to compile as
1026         // (later these will all be bound together as a program object)
1027         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1028         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1029         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030
1031         // the second pretext is the mode (for example a light source)
1032         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1033         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1034         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1035         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036
1037         // now add all the permutation pretexts
1038         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039         {
1040                 if (permutation & (1<<i))
1041                 {
1042                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046                 }
1047                 else
1048                 {
1049                         // keep line numbers correct
1050                         vertstrings_list[vertstrings_count++] = "\n";
1051                         geomstrings_list[geomstrings_count++] = "\n";
1052                         fragstrings_list[fragstrings_count++] = "\n";
1053                 }
1054         }
1055
1056         // add static parms
1057         R_CompileShader_AddStaticParms(mode, permutation);
1058         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         vertstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         geomstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         fragstrings_count += shaderstaticparms_count;
1064
1065         // now append the shader text itself
1066         vertstrings_list[vertstrings_count++] = vertexstring;
1067         geomstrings_list[geomstrings_count++] = geometrystring;
1068         fragstrings_list[fragstrings_count++] = fragmentstring;
1069
1070         // if any sources were NULL, clear the respective list
1071         if (!vertexstring)
1072                 vertstrings_count = 0;
1073         if (!geometrystring)
1074                 geomstrings_count = 0;
1075         if (!fragmentstring)
1076                 fragstrings_count = 0;
1077
1078         // compile the shader program
1079         if (vertstrings_count + geomstrings_count + fragstrings_count)
1080                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081         if (p->program)
1082         {
1083                 CHECKGLERROR
1084                 qglUseProgram(p->program);CHECKGLERROR
1085                 // look up all the uniform variable names we care about, so we don't
1086                 // have to look them up every time we set them
1087
1088                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1089                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1090                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1091                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1092                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1093                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1094                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1095                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1096                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1097                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1098                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1099                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1100                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1101                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1102                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1103                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1104                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1105                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1106                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1107                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1108                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1109                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1110                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1111                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1112                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1113                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1114                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1115                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1116                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1117                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1118                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1119                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1120                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1121                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1122                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1123                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1124                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1125                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1126                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1127                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1128                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1129                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1130                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1131                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1132                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1133                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1134                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1135                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1136                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1137                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1138                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1139                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1140                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1141                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1142                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1143                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1144                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1145                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1146                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1147                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1148                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1149                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1150                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1151                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1152                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1153                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1154                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1155                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1156                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1157                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1158                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1159                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1160                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1161                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1162                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1163                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1164                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1165                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1166                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1167                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1168                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1169                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1170                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1171                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1172                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1173                 // initialize the samplers to refer to the texture units we use
1174                 p->tex_Texture_First = -1;
1175                 p->tex_Texture_Second = -1;
1176                 p->tex_Texture_GammaRamps = -1;
1177                 p->tex_Texture_Normal = -1;
1178                 p->tex_Texture_Color = -1;
1179                 p->tex_Texture_Gloss = -1;
1180                 p->tex_Texture_Glow = -1;
1181                 p->tex_Texture_SecondaryNormal = -1;
1182                 p->tex_Texture_SecondaryColor = -1;
1183                 p->tex_Texture_SecondaryGloss = -1;
1184                 p->tex_Texture_SecondaryGlow = -1;
1185                 p->tex_Texture_Pants = -1;
1186                 p->tex_Texture_Shirt = -1;
1187                 p->tex_Texture_FogHeightTexture = -1;
1188                 p->tex_Texture_FogMask = -1;
1189                 p->tex_Texture_Lightmap = -1;
1190                 p->tex_Texture_Deluxemap = -1;
1191                 p->tex_Texture_Attenuation = -1;
1192                 p->tex_Texture_Cube = -1;
1193                 p->tex_Texture_Refraction = -1;
1194                 p->tex_Texture_Reflection = -1;
1195                 p->tex_Texture_ShadowMap2D = -1;
1196                 p->tex_Texture_CubeProjection = -1;
1197                 p->tex_Texture_ScreenDepth = -1;
1198                 p->tex_Texture_ScreenNormalMap = -1;
1199                 p->tex_Texture_ScreenDiffuse = -1;
1200                 p->tex_Texture_ScreenSpecular = -1;
1201                 p->tex_Texture_ReflectMask = -1;
1202                 p->tex_Texture_ReflectCube = -1;
1203                 p->tex_Texture_BounceGrid = -1;
1204                 sampler = 0;
1205                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1206                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1207                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1208                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1209                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1210                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1211                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1216                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1217                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1218                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1219                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1220                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1221                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1222                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1223                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1224                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1225                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1226                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1227                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1233                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1234                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1235                 CHECKGLERROR
1236                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1237         }
1238         else
1239                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1240
1241         // free the strings
1242         if (vertexstring)
1243                 Mem_Free(vertexstring);
1244         if (geometrystring)
1245                 Mem_Free(geometrystring);
1246         if (fragmentstring)
1247                 Mem_Free(fragmentstring);
1248 }
1249
1250 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1251 {
1252         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1253         if (r_glsl_permutation != perm)
1254         {
1255                 r_glsl_permutation = perm;
1256                 if (!r_glsl_permutation->program)
1257                 {
1258                         if (!r_glsl_permutation->compiled)
1259                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1260                         if (!r_glsl_permutation->program)
1261                         {
1262                                 // remove features until we find a valid permutation
1263                                 int i;
1264                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1265                                 {
1266                                         // reduce i more quickly whenever it would not remove any bits
1267                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1268                                         if (!(permutation & j))
1269                                                 continue;
1270                                         permutation -= j;
1271                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1272                                         if (!r_glsl_permutation->compiled)
1273                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1274                                         if (r_glsl_permutation->program)
1275                                                 break;
1276                                 }
1277                                 if (i >= SHADERPERMUTATION_COUNT)
1278                                 {
1279                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         qglUseProgram(0);CHECKGLERROR
1282                                         return; // no bit left to clear, entire mode is broken
1283                                 }
1284                         }
1285                 }
1286                 CHECKGLERROR
1287                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1288         }
1289         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1290         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1291         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1292 }
1293
1294 #ifdef SUPPORTD3D
1295
1296 #ifdef SUPPORTD3D
1297 #include <d3d9.h>
1298 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1299 extern D3DCAPS9 vid_d3d9caps;
1300 #endif
1301
1302 struct r_hlsl_permutation_s;
1303 typedef struct r_hlsl_permutation_s
1304 {
1305         /// hash lookup data
1306         struct r_hlsl_permutation_s *hashnext;
1307         unsigned int mode;
1308         unsigned int permutation;
1309
1310         /// indicates if we have tried compiling this permutation already
1311         qboolean compiled;
1312         /// NULL if compilation failed
1313         IDirect3DVertexShader9 *vertexshader;
1314         IDirect3DPixelShader9 *pixelshader;
1315 }
1316 r_hlsl_permutation_t;
1317
1318 typedef enum D3DVSREGISTER_e
1319 {
1320         D3DVSREGISTER_TexMatrix = 0, // float4x4
1321         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1322         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1323         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1324         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1325         D3DVSREGISTER_ModelToLight = 20, // float4x4
1326         D3DVSREGISTER_EyePosition = 24,
1327         D3DVSREGISTER_FogPlane = 25,
1328         D3DVSREGISTER_LightDir = 26,
1329         D3DVSREGISTER_LightPosition = 27,
1330 }
1331 D3DVSREGISTER_t;
1332
1333 typedef enum D3DPSREGISTER_e
1334 {
1335         D3DPSREGISTER_Alpha = 0,
1336         D3DPSREGISTER_BloomBlur_Parameters = 1,
1337         D3DPSREGISTER_ClientTime = 2,
1338         D3DPSREGISTER_Color_Ambient = 3,
1339         D3DPSREGISTER_Color_Diffuse = 4,
1340         D3DPSREGISTER_Color_Specular = 5,
1341         D3DPSREGISTER_Color_Glow = 6,
1342         D3DPSREGISTER_Color_Pants = 7,
1343         D3DPSREGISTER_Color_Shirt = 8,
1344         D3DPSREGISTER_DeferredColor_Ambient = 9,
1345         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1346         D3DPSREGISTER_DeferredColor_Specular = 11,
1347         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1348         D3DPSREGISTER_DeferredMod_Specular = 13,
1349         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1350         D3DPSREGISTER_EyePosition = 15, // unused
1351         D3DPSREGISTER_FogColor = 16,
1352         D3DPSREGISTER_FogHeightFade = 17,
1353         D3DPSREGISTER_FogPlane = 18,
1354         D3DPSREGISTER_FogPlaneViewDist = 19,
1355         D3DPSREGISTER_FogRangeRecip = 20,
1356         D3DPSREGISTER_LightColor = 21,
1357         D3DPSREGISTER_LightDir = 22, // unused
1358         D3DPSREGISTER_LightPosition = 23,
1359         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1360         D3DPSREGISTER_PixelSize = 25,
1361         D3DPSREGISTER_ReflectColor = 26,
1362         D3DPSREGISTER_ReflectFactor = 27,
1363         D3DPSREGISTER_ReflectOffset = 28,
1364         D3DPSREGISTER_RefractColor = 29,
1365         D3DPSREGISTER_Saturation = 30,
1366         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1367         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1368         D3DPSREGISTER_ScreenToDepth = 33,
1369         D3DPSREGISTER_ShadowMap_Parameters = 34,
1370         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1371         D3DPSREGISTER_SpecularPower = 36,
1372         D3DPSREGISTER_UserVec1 = 37,
1373         D3DPSREGISTER_UserVec2 = 38,
1374         D3DPSREGISTER_UserVec3 = 39,
1375         D3DPSREGISTER_UserVec4 = 40,
1376         D3DPSREGISTER_ViewTintColor = 41,
1377         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1378         D3DPSREGISTER_BloomColorSubtract = 43,
1379         D3DPSREGISTER_ViewToLight = 44, // float4x4
1380         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1381         D3DPSREGISTER_NormalmapScrollBlend = 52,
1382         // next at 53
1383 }
1384 D3DPSREGISTER_t;
1385
1386 /// information about each possible shader permutation
1387 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1388 /// currently selected permutation
1389 r_hlsl_permutation_t *r_hlsl_permutation;
1390 /// storage for permutations linked in the hash table
1391 memexpandablearray_t r_hlsl_permutationarray;
1392
1393 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1394 {
1395         //unsigned int hashdepth = 0;
1396         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1397         r_hlsl_permutation_t *p;
1398         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1399         {
1400                 if (p->mode == mode && p->permutation == permutation)
1401                 {
1402                         //if (hashdepth > 10)
1403                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404                         return p;
1405                 }
1406                 //hashdepth++;
1407         }
1408         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1409         p->mode = mode;
1410         p->permutation = permutation;
1411         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1412         r_hlsl_permutationhash[mode][hashindex] = p;
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
1418 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1419 {
1420         char *shaderstring;
1421         if (!filename || !filename[0])
1422                 return NULL;
1423         if (!strcmp(filename, "hlsl/default.hlsl"))
1424         {
1425                 if (!hlslshaderstring)
1426                 {
1427                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428                         if (hlslshaderstring)
1429                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1430                         else
1431                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1432                 }
1433                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1434                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1435                 return shaderstring;
1436         }
1437         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438         if (shaderstring)
1439         {
1440                 if (printfromdisknotice)
1441                         Con_DPrintf("from disk %s... ", filename);
1442                 return shaderstring;
1443         }
1444         return shaderstring;
1445 }
1446
1447 #include <d3dx9.h>
1448 //#include <d3dx9shader.h>
1449 //#include <d3dx9mesh.h>
1450
1451 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1452 {
1453         DWORD *vsbin = NULL;
1454         DWORD *psbin = NULL;
1455         fs_offset_t vsbinsize;
1456         fs_offset_t psbinsize;
1457 //      IDirect3DVertexShader9 *vs = NULL;
1458 //      IDirect3DPixelShader9 *ps = NULL;
1459         ID3DXBuffer *vslog = NULL;
1460         ID3DXBuffer *vsbuffer = NULL;
1461         ID3DXConstantTable *vsconstanttable = NULL;
1462         ID3DXBuffer *pslog = NULL;
1463         ID3DXBuffer *psbuffer = NULL;
1464         ID3DXConstantTable *psconstanttable = NULL;
1465         int vsresult = 0;
1466         int psresult = 0;
1467         char temp[MAX_INPUTLINE];
1468         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1469         qboolean debugshader = gl_paranoid.integer != 0;
1470         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (!debugshader)
1473         {
1474                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1475                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1476         }
1477         if ((!vsbin && vertstring) || (!psbin && fragstring))
1478         {
1479                 const char* dllnames_d3dx9 [] =
1480                 {
1481                         "d3dx9_43.dll",
1482                         "d3dx9_42.dll",
1483                         "d3dx9_41.dll",
1484                         "d3dx9_40.dll",
1485                         "d3dx9_39.dll",
1486                         "d3dx9_38.dll",
1487                         "d3dx9_37.dll",
1488                         "d3dx9_36.dll",
1489                         "d3dx9_35.dll",
1490                         "d3dx9_34.dll",
1491                         "d3dx9_33.dll",
1492                         "d3dx9_32.dll",
1493                         "d3dx9_31.dll",
1494                         "d3dx9_30.dll",
1495                         "d3dx9_29.dll",
1496                         "d3dx9_28.dll",
1497                         "d3dx9_27.dll",
1498                         "d3dx9_26.dll",
1499                         "d3dx9_25.dll",
1500                         "d3dx9_24.dll",
1501                         NULL
1502                 };
1503                 dllhandle_t d3dx9_dll = NULL;
1504                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1505                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1506                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 dllfunction_t d3dx9_dllfuncs[] =
1508                 {
1509                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1510                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1511                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1512                         {NULL, NULL}
1513                 };
1514                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1515                 {
1516                         DWORD shaderflags = 0;
1517                         if (debugshader)
1518                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1519                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1520                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1521                         if (vertstring && vertstring[0])
1522                         {
1523                                 if (debugshader)
1524                                 {
1525 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1526 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1527                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1528                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529                                 }
1530                                 else
1531                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532                                 if (vsbuffer)
1533                                 {
1534                                         vsbinsize = vsbuffer->GetBufferSize();
1535                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1536                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1537                                         vsbuffer->Release();
1538                                 }
1539                                 if (vslog)
1540                                 {
1541                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1542                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1543                                         vslog->Release();
1544                                 }
1545                         }
1546                         if (fragstring && fragstring[0])
1547                         {
1548                                 if (debugshader)
1549                                 {
1550 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1551 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1552                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1553                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554                                 }
1555                                 else
1556                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557                                 if (psbuffer)
1558                                 {
1559                                         psbinsize = psbuffer->GetBufferSize();
1560                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1561                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1562                                         psbuffer->Release();
1563                                 }
1564                                 if (pslog)
1565                                 {
1566                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1567                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1568                                         pslog->Release();
1569                                 }
1570                         }
1571                         Sys_UnloadLibrary(&d3dx9_dll);
1572                 }
1573                 else
1574                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1575         }
1576         if (vsbin && psbin)
1577         {
1578                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1579                 if (FAILED(vsresult))
1580                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1581                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1582                 if (FAILED(psresult))
1583                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1584         }
1585         // free the shader data
1586         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1587         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1588 }
1589
1590 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1591 {
1592         int i;
1593         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1594         int vertstring_length = 0;
1595         int geomstring_length = 0;
1596         int fragstring_length = 0;
1597         char *t;
1598         char *vertexstring, *geometrystring, *fragmentstring;
1599         char *vertstring, *geomstring, *fragstring;
1600         char permutationname[256];
1601         char cachename[256];
1602         int vertstrings_count = 0;
1603         int geomstrings_count = 0;
1604         int fragstrings_count = 0;
1605         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608
1609         if (p->compiled)
1610                 return;
1611         p->compiled = true;
1612         p->vertexshader = NULL;
1613         p->pixelshader = NULL;
1614
1615         permutationname[0] = 0;
1616         cachename[0] = 0;
1617         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1618         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1619         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1620
1621         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1622         strlcat(cachename, "hlsl/", sizeof(cachename));
1623
1624         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1625         vertstrings_count = 0;
1626         geomstrings_count = 0;
1627         fragstrings_count = 0;
1628         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1629         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1630         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1631
1632         // the first pretext is which type of shader to compile as
1633         // (later these will all be bound together as a program object)
1634         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1635         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1636         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1637
1638         // the second pretext is the mode (for example a light source)
1639         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1640         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1641         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1642         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1643         strlcat(cachename, modeinfo->name, sizeof(cachename));
1644
1645         // now add all the permutation pretexts
1646         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1647         {
1648                 if (permutation & (1<<i))
1649                 {
1650                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1651                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1654                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1655                 }
1656                 else
1657                 {
1658                         // keep line numbers correct
1659                         vertstrings_list[vertstrings_count++] = "\n";
1660                         geomstrings_list[geomstrings_count++] = "\n";
1661                         fragstrings_list[fragstrings_count++] = "\n";
1662                 }
1663         }
1664
1665         // add static parms
1666         R_CompileShader_AddStaticParms(mode, permutation);
1667         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         vertstrings_count += shaderstaticparms_count;
1669         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         geomstrings_count += shaderstaticparms_count;
1671         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         fragstrings_count += shaderstaticparms_count;
1673
1674         // replace spaces in the cachename with _ characters
1675         for (i = 0;cachename[i];i++)
1676                 if (cachename[i] == ' ')
1677                         cachename[i] = '_';
1678
1679         // now append the shader text itself
1680         vertstrings_list[vertstrings_count++] = vertexstring;
1681         geomstrings_list[geomstrings_count++] = geometrystring;
1682         fragstrings_list[fragstrings_count++] = fragmentstring;
1683
1684         // if any sources were NULL, clear the respective list
1685         if (!vertexstring)
1686                 vertstrings_count = 0;
1687         if (!geometrystring)
1688                 geomstrings_count = 0;
1689         if (!fragmentstring)
1690                 fragstrings_count = 0;
1691
1692         vertstring_length = 0;
1693         for (i = 0;i < vertstrings_count;i++)
1694                 vertstring_length += strlen(vertstrings_list[i]);
1695         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1696         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1697                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1698
1699         geomstring_length = 0;
1700         for (i = 0;i < geomstrings_count;i++)
1701                 geomstring_length += strlen(geomstrings_list[i]);
1702         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1703         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1704                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1705
1706         fragstring_length = 0;
1707         for (i = 0;i < fragstrings_count;i++)
1708                 fragstring_length += strlen(fragstrings_list[i]);
1709         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1710         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1711                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1712
1713         // try to load the cached shader, or generate one
1714         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1715
1716         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1717                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1718         else
1719                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1720
1721         // free the strings
1722         if (vertstring)
1723                 Mem_Free(vertstring);
1724         if (geomstring)
1725                 Mem_Free(geomstring);
1726         if (fragstring)
1727                 Mem_Free(fragstring);
1728         if (vertexstring)
1729                 Mem_Free(vertexstring);
1730         if (geometrystring)
1731                 Mem_Free(geometrystring);
1732         if (fragmentstring)
1733                 Mem_Free(fragmentstring);
1734 }
1735
1736 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1737 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1738 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);}
1739 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);}
1740 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);}
1741 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);}
1742
1743 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1744 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1745 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);}
1746 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);}
1747 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);}
1748 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);}
1749
1750 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1751 {
1752         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1753         if (r_hlsl_permutation != perm)
1754         {
1755                 r_hlsl_permutation = perm;
1756                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757                 {
1758                         if (!r_hlsl_permutation->compiled)
1759                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1760                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761                         {
1762                                 // remove features until we find a valid permutation
1763                                 int i;
1764                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1765                                 {
1766                                         // reduce i more quickly whenever it would not remove any bits
1767                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1768                                         if (!(permutation & j))
1769                                                 continue;
1770                                         permutation -= j;
1771                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1772                                         if (!r_hlsl_permutation->compiled)
1773                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1774                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1775                                                 break;
1776                                 }
1777                                 if (i >= SHADERPERMUTATION_COUNT)
1778                                 {
1779                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1780                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1781                                         return; // no bit left to clear, entire mode is broken
1782                                 }
1783                         }
1784                 }
1785                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1786                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1787         }
1788         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1790         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1791 }
1792 #endif
1793
1794 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1795 {
1796         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1797         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1799         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1800 }
1801
1802 void R_GLSL_Restart_f(void)
1803 {
1804         unsigned int i, limit;
1805         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1806                 Mem_Free(glslshaderstring);
1807         glslshaderstring = NULL;
1808         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1809                 Mem_Free(hlslshaderstring);
1810         hlslshaderstring = NULL;
1811         switch(vid.renderpath)
1812         {
1813         case RENDERPATH_D3D9:
1814 #ifdef SUPPORTD3D
1815                 {
1816                         r_hlsl_permutation_t *p;
1817                         r_hlsl_permutation = NULL;
1818                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1819                         for (i = 0;i < limit;i++)
1820                         {
1821                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1822                                 {
1823                                         if (p->vertexshader)
1824                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1825                                         if (p->pixelshader)
1826                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1827                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1828                                 }
1829                         }
1830                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1831                 }
1832 #endif
1833                 break;
1834         case RENDERPATH_D3D10:
1835                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836                 break;
1837         case RENDERPATH_D3D11:
1838                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839                 break;
1840         case RENDERPATH_GL20:
1841         case RENDERPATH_GLES2:
1842                 {
1843                         r_glsl_permutation_t *p;
1844                         r_glsl_permutation = NULL;
1845                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1846                         for (i = 0;i < limit;i++)
1847                         {
1848                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1849                                 {
1850                                         GL_Backend_FreeProgram(p->program);
1851                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1852                                 }
1853                         }
1854                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1855                 }
1856                 break;
1857         case RENDERPATH_GL11:
1858         case RENDERPATH_GL13:
1859         case RENDERPATH_GLES1:
1860                 break;
1861         case RENDERPATH_SOFT:
1862                 break;
1863         }
1864 }
1865
1866 void R_GLSL_DumpShader_f(void)
1867 {
1868         int i;
1869         qfile_t *file;
1870
1871         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1872         if (file)
1873         {
1874                 FS_Print(file, "/* The engine may define the following macros:\n");
1875                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1876                 for (i = 0;i < SHADERMODE_COUNT;i++)
1877                         FS_Print(file, glslshadermodeinfo[i].pretext);
1878                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879                         FS_Print(file, shaderpermutationinfo[i].pretext);
1880                 FS_Print(file, "*/\n");
1881                 FS_Print(file, builtinshaderstring);
1882                 FS_Close(file);
1883                 Con_Printf("glsl/default.glsl written\n");
1884         }
1885         else
1886                 Con_Printf("failed to write to glsl/default.glsl\n");
1887
1888         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1889         if (file)
1890         {
1891                 FS_Print(file, "/* The engine may define the following macros:\n");
1892                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1893                 for (i = 0;i < SHADERMODE_COUNT;i++)
1894                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1895                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1896                         FS_Print(file, shaderpermutationinfo[i].pretext);
1897                 FS_Print(file, "*/\n");
1898                 FS_Print(file, builtinhlslshaderstring);
1899                 FS_Close(file);
1900                 Con_Printf("hlsl/default.hlsl written\n");
1901         }
1902         else
1903                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1904 }
1905
1906 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1907 {
1908         unsigned int permutation = 0;
1909         if (r_trippy.integer && !notrippy)
1910                 permutation |= SHADERPERMUTATION_TRIPPY;
1911         permutation |= SHADERPERMUTATION_VIEWTINT;
1912         if (first)
1913                 permutation |= SHADERPERMUTATION_DIFFUSE;
1914         if (second)
1915                 permutation |= SHADERPERMUTATION_SPECULAR;
1916         if (texturemode == GL_MODULATE)
1917                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1918         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1919                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1920         else if (texturemode == GL_ADD)
1921                 permutation |= SHADERPERMUTATION_GLOW;
1922         else if (texturemode == GL_DECAL)
1923                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1924         if (!second)
1925                 texturemode = GL_MODULATE;
1926         if (vid.allowalphatocoverage)
1927                 GL_AlphaToCoverage(false);
1928         switch (vid.renderpath)
1929         {
1930         case RENDERPATH_D3D9:
1931 #ifdef SUPPORTD3D
1932                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1933                 R_Mesh_TexBind(GL20TU_FIRST , first );
1934                 R_Mesh_TexBind(GL20TU_SECOND, second);
1935                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1936                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1937 #endif
1938                 break;
1939         case RENDERPATH_D3D10:
1940                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941                 break;
1942         case RENDERPATH_D3D11:
1943                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_GL20:
1946         case RENDERPATH_GLES2:
1947                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1949                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1950                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952                 break;
1953         case RENDERPATH_GL13:
1954         case RENDERPATH_GLES1:
1955                 R_Mesh_TexBind(0, first );
1956                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1957                 R_Mesh_TexBind(1, second);
1958                 if (second)
1959                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1960                 break;
1961         case RENDERPATH_GL11:
1962                 R_Mesh_TexBind(0, first );
1963                 break;
1964         case RENDERPATH_SOFT:
1965                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1966                 R_Mesh_TexBind(GL20TU_FIRST , first );
1967                 R_Mesh_TexBind(GL20TU_SECOND, second);
1968                 break;
1969         }
1970 }
1971
1972 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1973 {
1974         unsigned int permutation = 0;
1975         if (r_trippy.integer && !notrippy)
1976                 permutation |= SHADERPERMUTATION_TRIPPY;
1977         if (vid.allowalphatocoverage)
1978                 GL_AlphaToCoverage(false);
1979         switch (vid.renderpath)
1980         {
1981         case RENDERPATH_D3D9:
1982 #ifdef SUPPORTD3D
1983                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1984 #endif
1985                 break;
1986         case RENDERPATH_D3D10:
1987                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1988                 break;
1989         case RENDERPATH_D3D11:
1990                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991                 break;
1992         case RENDERPATH_GL20:
1993         case RENDERPATH_GLES2:
1994                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995                 break;
1996         case RENDERPATH_GL13:
1997         case RENDERPATH_GLES1:
1998                 R_Mesh_TexBind(0, 0);
1999                 R_Mesh_TexBind(1, 0);
2000                 break;
2001         case RENDERPATH_GL11:
2002                 R_Mesh_TexBind(0, 0);
2003                 break;
2004         case RENDERPATH_SOFT:
2005                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         }
2008 }
2009
2010 void R_SetupShader_ShowDepth(qboolean notrippy)
2011 {
2012         int permutation = 0;
2013         if (r_trippy.integer && !notrippy)
2014                 permutation |= SHADERPERMUTATION_TRIPPY;
2015         if (vid.allowalphatocoverage)
2016                 GL_AlphaToCoverage(false);
2017         switch (vid.renderpath)
2018         {
2019         case RENDERPATH_D3D9:
2020 #ifdef SUPPORTHLSL
2021                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2022 #endif
2023                 break;
2024         case RENDERPATH_D3D10:
2025                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2026                 break;
2027         case RENDERPATH_D3D11:
2028                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2029                 break;
2030         case RENDERPATH_GL20:
2031         case RENDERPATH_GLES2:
2032                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2033                 break;
2034         case RENDERPATH_GL13:
2035         case RENDERPATH_GLES1:
2036                 break;
2037         case RENDERPATH_GL11:
2038                 break;
2039         case RENDERPATH_SOFT:
2040                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2041                 break;
2042         }
2043 }
2044
2045 extern qboolean r_shadow_usingdeferredprepass;
2046 extern cvar_t r_shadow_deferred_8bitrange;
2047 extern rtexture_t *r_shadow_attenuationgradienttexture;
2048 extern rtexture_t *r_shadow_attenuation2dtexture;
2049 extern rtexture_t *r_shadow_attenuation3dtexture;
2050 extern qboolean r_shadow_usingshadowmap2d;
2051 extern qboolean r_shadow_usingshadowmaportho;
2052 extern float r_shadow_shadowmap_texturescale[2];
2053 extern float r_shadow_shadowmap_parameters[4];
2054 extern qboolean r_shadow_shadowmapvsdct;
2055 extern qboolean r_shadow_shadowmapsampler;
2056 extern int r_shadow_shadowmappcf;
2057 extern rtexture_t *r_shadow_shadowmap2dtexture;
2058 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2059 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2060 extern matrix4x4_t r_shadow_shadowmapmatrix;
2061 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2062 extern int r_shadow_prepass_width;
2063 extern int r_shadow_prepass_height;
2064 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2065 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2066 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2067 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2068 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2069
2070 #define BLENDFUNC_ALLOWS_COLORMOD      1
2071 #define BLENDFUNC_ALLOWS_FOG           2
2072 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2073 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2074 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2075 static int R_BlendFuncFlags(int src, int dst)
2076 {
2077         int r = 0;
2078
2079         // a blendfunc allows colormod if:
2080         // a) it can never keep the destination pixel invariant, or
2081         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2082         // this is to prevent unintended side effects from colormod
2083
2084         // a blendfunc allows fog if:
2085         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2086         // this is to prevent unintended side effects from fog
2087
2088         // these checks are the output of fogeval.pl
2089
2090         r |= BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2100         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112
2113         return r;
2114 }
2115
2116 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)
2117 {
2118         // select a permutation of the lighting shader appropriate to this
2119         // combination of texture, entity, light source, and fogging, only use the
2120         // minimum features necessary to avoid wasting rendering time in the
2121         // fragment shader on features that are not being used
2122         unsigned int permutation = 0;
2123         unsigned int mode = 0;
2124         int blendfuncflags;
2125         static float dummy_colormod[3] = {1, 1, 1};
2126         float *colormod = rsurface.colormod;
2127         float m16f[16];
2128         matrix4x4_t tempmatrix;
2129         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2130         if (r_trippy.integer && !notrippy)
2131                 permutation |= SHADERPERMUTATION_TRIPPY;
2132         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2133                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2134         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2135                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2136         if (rsurfacepass == RSURFPASS_BACKGROUND)
2137         {
2138                 // distorted background
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2140                 {
2141                         mode = SHADERMODE_WATER;
2142                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2143                         {
2144                                 // this is the right thing to do for wateralpha
2145                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2147                         }
2148                         else
2149                         {
2150                                 // this is the right thing to do for entity alpha
2151                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                         }
2154                 }
2155                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2156                 {
2157                         mode = SHADERMODE_REFRACTION;
2158                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160                 }
2161                 else
2162                 {
2163                         mode = SHADERMODE_GENERIC;
2164                         permutation |= SHADERPERMUTATION_DIFFUSE;
2165                         GL_BlendFunc(GL_ONE, GL_ZERO);
2166                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167                 }
2168                 if (vid.allowalphatocoverage)
2169                         GL_AlphaToCoverage(false);
2170         }
2171         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2172         {
2173                 if (r_glsl_offsetmapping.integer)
2174                 {
2175                         switch(rsurface.texture->offsetmapping)
2176                         {
2177                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2178                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2179                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180                         case OFFSETMAPPING_OFF: break;
2181                         }
2182                 }
2183                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2184                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2185                 // normalmap (deferred prepass), may use alpha test on diffuse
2186                 mode = SHADERMODE_DEFERREDGEOMETRY;
2187                 GL_BlendFunc(GL_ONE, GL_ZERO);
2188                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2189                 if (vid.allowalphatocoverage)
2190                         GL_AlphaToCoverage(false);
2191         }
2192         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2193         {
2194                 if (r_glsl_offsetmapping.integer)
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // light source
2207                 mode = SHADERMODE_LIGHTSOURCE;
2208                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2209                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2210                 if (diffusescale > 0)
2211                         permutation |= SHADERPERMUTATION_DIFFUSE;
2212                 if (specularscale > 0)
2213                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2214                 if (r_refdef.fogenabled)
2215                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2216                 if (rsurface.texture->colormapping)
2217                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2218                 if (r_shadow_usingshadowmap2d)
2219                 {
2220                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221                         if(r_shadow_shadowmapvsdct)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2223
2224                         if (r_shadow_shadowmapsampler)
2225                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226                         if (r_shadow_shadowmappcf > 1)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228                         else if (r_shadow_shadowmappcf)
2229                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2230                 }
2231                 if (rsurface.texture->reflectmasktexture)
2232                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2234                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2235                 if (vid.allowalphatocoverage)
2236                         GL_AlphaToCoverage(false);
2237         }
2238         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2239         {
2240                 if (r_glsl_offsetmapping.integer)
2241                 {
2242                         switch(rsurface.texture->offsetmapping)
2243                         {
2244                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2245                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2246                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247                         case OFFSETMAPPING_OFF: break;
2248                         }
2249                 }
2250                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2251                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2252                 // unshaded geometry (fullbright or ambient model lighting)
2253                 mode = SHADERMODE_FLATCOLOR;
2254                 ambientscale = diffusescale = specularscale = 0;
2255                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2256                         permutation |= SHADERPERMUTATION_GLOW;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265
2266                         if (r_shadow_shadowmapsampler)
2267                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268                         if (r_shadow_shadowmappcf > 1)
2269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270                         else if (r_shadow_shadowmappcf)
2271                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274                         permutation |= SHADERPERMUTATION_REFLECTION;
2275                 if (rsurface.texture->reflectmasktexture)
2276                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2277                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2278                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 // when using alphatocoverage, we don't need alphakill
2280                 if (vid.allowalphatocoverage)
2281                 {
2282                         if (r_transparent_alphatocoverage.integer)
2283                         {
2284                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2285                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2286                         }
2287                         else
2288                                 GL_AlphaToCoverage(false);
2289                 }
2290         }
2291         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2292         {
2293                 if (r_glsl_offsetmapping.integer)
2294                 {
2295                         switch(rsurface.texture->offsetmapping)
2296                         {
2297                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2298                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2299                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_OFF: break;
2301                         }
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2304                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2305                 // directional model lighting
2306                 mode = SHADERMODE_LIGHTDIRECTION;
2307                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2308                         permutation |= SHADERPERMUTATION_GLOW;
2309                 permutation |= SHADERPERMUTATION_DIFFUSE;
2310                 if (specularscale > 0)
2311                         permutation |= SHADERPERMUTATION_SPECULAR;
2312                 if (r_refdef.fogenabled)
2313                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2314                 if (rsurface.texture->colormapping)
2315                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2316                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2317                 {
2318                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2319                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2320
2321                         if (r_shadow_shadowmapsampler)
2322                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2323                         if (r_shadow_shadowmappcf > 1)
2324                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2325                         else if (r_shadow_shadowmappcf)
2326                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2327                 }
2328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2329                         permutation |= SHADERPERMUTATION_REFLECTION;
2330                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2331                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2332                 if (rsurface.texture->reflectmasktexture)
2333                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334                 if (r_shadow_bouncegridtexture)
2335                 {
2336                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2337                         if (r_shadow_bouncegriddirectional)
2338                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2339                 }
2340                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2341                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 // when using alphatocoverage, we don't need alphakill
2343                 if (vid.allowalphatocoverage)
2344                 {
2345                         if (r_transparent_alphatocoverage.integer)
2346                         {
2347                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2348                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2349                         }
2350                         else
2351                                 GL_AlphaToCoverage(false);
2352                 }
2353         }
2354         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2355         {
2356                 if (r_glsl_offsetmapping.integer)
2357                 {
2358                         switch(rsurface.texture->offsetmapping)
2359                         {
2360                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2361                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2362                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_OFF: break;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // ambient model lighting
2369                 mode = SHADERMODE_LIGHTDIRECTION;
2370                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371                         permutation |= SHADERPERMUTATION_GLOW;
2372                 if (r_refdef.fogenabled)
2373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374                 if (rsurface.texture->colormapping)
2375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377                 {
2378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380
2381                         if (r_shadow_shadowmapsampler)
2382                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2383                         if (r_shadow_shadowmappcf > 1)
2384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2385                         else if (r_shadow_shadowmappcf)
2386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2389                         permutation |= SHADERPERMUTATION_REFLECTION;
2390                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2391                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2392                 if (rsurface.texture->reflectmasktexture)
2393                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2394                 if (r_shadow_bouncegridtexture)
2395                 {
2396                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2397                         if (r_shadow_bouncegriddirectional)
2398                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2399                 }
2400                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2401                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402                 // when using alphatocoverage, we don't need alphakill
2403                 if (vid.allowalphatocoverage)
2404                 {
2405                         if (r_transparent_alphatocoverage.integer)
2406                         {
2407                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2408                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2409                         }
2410                         else
2411                                 GL_AlphaToCoverage(false);
2412                 }
2413         }
2414         else
2415         {
2416                 if (r_glsl_offsetmapping.integer)
2417                 {
2418                         switch(rsurface.texture->offsetmapping)
2419                         {
2420                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2421                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2422                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423                         case OFFSETMAPPING_OFF: break;
2424                         }
2425                 }
2426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2428                 // lightmapped wall
2429                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2430                         permutation |= SHADERPERMUTATION_GLOW;
2431                 if (r_refdef.fogenabled)
2432                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2433                 if (rsurface.texture->colormapping)
2434                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2435                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2436                 {
2437                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2438                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2439
2440                         if (r_shadow_shadowmapsampler)
2441                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2442                         if (r_shadow_shadowmappcf > 1)
2443                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2444                         else if (r_shadow_shadowmappcf)
2445                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2446                 }
2447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2448                         permutation |= SHADERPERMUTATION_REFLECTION;
2449                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2450                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2451                 if (rsurface.texture->reflectmasktexture)
2452                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2453                 if (FAKELIGHT_ENABLED)
2454                 {
2455                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2456                         mode = SHADERMODE_FAKELIGHT;
2457                         permutation |= SHADERPERMUTATION_DIFFUSE;
2458                         if (specularscale > 0)
2459                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2460                 }
2461                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2462                 {
2463                         // deluxemapping (light direction texture)
2464                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2466                         else
2467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 2)
2473                 {
2474                         // fake deluxemapping (uniform light direction in tangentspace)
2475                         if (rsurface.uselightmaptexture)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (rsurface.uselightmaptexture)
2484                 {
2485                         // ordinary lightmapping (q1bsp, q3bsp)
2486                         mode = SHADERMODE_LIGHTMAP;
2487                 }
2488                 else
2489                 {
2490                         // ordinary vertex coloring (q3bsp)
2491                         mode = SHADERMODE_VERTEXCOLOR;
2492                 }
2493                 if (r_shadow_bouncegridtexture)
2494                 {
2495                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2496                         if (r_shadow_bouncegriddirectional)
2497                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2498                 }
2499                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2500                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 // when using alphatocoverage, we don't need alphakill
2502                 if (vid.allowalphatocoverage)
2503                 {
2504                         if (r_transparent_alphatocoverage.integer)
2505                         {
2506                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2507                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2508                         }
2509                         else
2510                                 GL_AlphaToCoverage(false);
2511                 }
2512         }
2513         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2514                 colormod = dummy_colormod;
2515         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2516                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2517         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2518                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2519         switch(vid.renderpath)
2520         {
2521         case RENDERPATH_D3D9:
2522 #ifdef SUPPORTD3D
2523                 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);
2524                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2525                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2527                 if (mode == SHADERMODE_LIGHTSOURCE)
2528                 {
2529                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2530                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                 }
2532                 else
2533                 {
2534                         if (mode == SHADERMODE_LIGHTDIRECTION)
2535                         {
2536                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2537                         }
2538                 }
2539                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2542                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2543                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2544
2545                 if (mode == SHADERMODE_LIGHTSOURCE)
2546                 {
2547                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2552
2553                         // additive passes are only darkened by fog, not tinted
2554                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2555                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2556                 }
2557                 else
2558                 {
2559                         if (mode == SHADERMODE_FLATCOLOR)
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2562                         }
2563                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2564                         {
2565                                 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]);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2567                                 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);
2568                                 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);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2572                         }
2573                         else
2574                         {
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2577                                 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);
2578                                 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);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2580                         }
2581                         // additive passes are only darkened by fog, not tinted
2582                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2584                         else
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2586                         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);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2594                         if (mode == SHADERMODE_WATER)
2595                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2596                 }
2597                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2598                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2599                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2600                 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));
2601                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2602                 if (rsurface.texture->pantstexture)
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2604                 else
2605                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2606                 if (rsurface.texture->shirttexture)
2607                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2608                 else
2609                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2610                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2611                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2614                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2615                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2616                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2617                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2619                         );
2620                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2621                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2622
2623                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2624                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2625                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2626                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2627                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2631                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2632                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2633                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2634                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2635                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2636                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2637                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2638                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2639                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2640                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2641                 {
2642                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2643                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2644                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646                 else
2647                 {
2648                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2649                 }
2650 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2651 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2652                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2653                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2654                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2655                 {
2656                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2657                         if (rsurface.rtlight)
2658                         {
2659                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2660                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2661                         }
2662                 }
2663 #endif
2664                 break;
2665         case RENDERPATH_D3D10:
2666                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2667                 break;
2668         case RENDERPATH_D3D11:
2669                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2670                 break;
2671         case RENDERPATH_GL20:
2672         case RENDERPATH_GLES2:
2673                 if (!vid.useinterleavedarrays)
2674                 {
2675                         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);
2676                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2677                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2683                 }
2684                 else
2685                 {
2686                         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);
2687                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2688                 }
2689                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2690                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2691                 if (mode == SHADERMODE_LIGHTSOURCE)
2692                 {
2693                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2694                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2695                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2696                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2697                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2698                         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);
2699         
2700                         // additive passes are only darkened by fog, not tinted
2701                         if (r_glsl_permutation->loc_FogColor >= 0)
2702                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2703                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2704                 }
2705                 else
2706                 {
2707                         if (mode == SHADERMODE_FLATCOLOR)
2708                         {
2709                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2710                         }
2711                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2712                         {
2713                                 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]);
2714                                 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]);
2715                                 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);
2716                                 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);
2717                                 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);
2718                                 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]);
2719                                 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]);
2720                         }
2721                         else
2722                         {
2723                                 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]);
2724                                 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]);
2725                                 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);
2726                                 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);
2727                                 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);
2728                         }
2729                         // additive passes are only darkened by fog, not tinted
2730                         if (r_glsl_permutation->loc_FogColor >= 0)
2731                         {
2732                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2733                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2734                                 else
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2736                         }
2737                         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);
2738                         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]);
2739                         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]);
2740                         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]);
2741                         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]);
2742                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2743                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2744                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2745                         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]);
2746                 }
2747                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2750                 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]);
2751                 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]);
2752
2753                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2754                 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));
2755                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2756                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2757                 {
2758                         if (rsurface.texture->pantstexture)
2759                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2760                         else
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2762                 }
2763                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2764                 {
2765                         if (rsurface.texture->shirttexture)
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2767                         else
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2769                 }
2770                 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]);
2771                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2772                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2773                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2774                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2775                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2776                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2777                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2779                         );
2780                 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]);
2781                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2782                 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);}
2783                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2784
2785                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2786                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2787                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2788                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2789                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2790                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2791                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2796                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2797                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2798                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2799                 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);
2800                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2801                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2802                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2803                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2804                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2805                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2806                 {
2807                         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);
2808                         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);
2809                         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);
2810                 }
2811                 else
2812                 {
2813                         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);
2814                 }
2815                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2816                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2817                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2818                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2819                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2820                 {
2821                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2822                         if (rsurface.rtlight)
2823                         {
2824                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2825                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2826                         }
2827                 }
2828                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2829                 CHECKGLERROR
2830                 break;
2831         case RENDERPATH_GL11:
2832         case RENDERPATH_GL13:
2833         case RENDERPATH_GLES1:
2834                 break;
2835         case RENDERPATH_SOFT:
2836                 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);
2837                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2838                 R_SetupShader_SetPermutationSoft(mode, permutation);
2839                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2840                 if (mode == SHADERMODE_LIGHTSOURCE)
2841                 {
2842                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2848         
2849                         // additive passes are only darkened by fog, not tinted
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2851                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2852                 }
2853                 else
2854                 {
2855                         if (mode == SHADERMODE_FLATCOLOR)
2856                         {
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2858                         }
2859                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2860                         {
2861                                 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]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2863                                 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);
2864                                 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);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2866                                 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]);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2868                         }
2869                         else
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2873                                 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);
2874                                 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);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2876                         }
2877                         // additive passes are only darkened by fog, not tinted
2878                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2880                         else
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2882                         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);
2883                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2884                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2885                         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]);
2886                         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]);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2889                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2890                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2891                 }
2892                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2893                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2894                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2895                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2896                 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]);
2897
2898                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2899                 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));
2900                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2901                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2902                 {
2903                         if (rsurface.texture->pantstexture)
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2905                         else
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2907                 }
2908                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2909                 {
2910                         if (rsurface.texture->shirttexture)
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2912                         else
2913                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2914                 }
2915                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2919                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2920                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2921                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2922                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2924                         );
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2927
2928                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2929                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2930                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2931                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2940                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2941                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2942                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2943                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2944                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2945                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2946                 {
2947                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2948                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2949                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2950                 }
2951                 else
2952                 {
2953                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954                 }
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2991         // light source
2992         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2993         if (rtlight->currentcubemap != r_texture_whitecube)
2994                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2995         if (diffusescale > 0)
2996                 permutation |= SHADERPERMUTATION_DIFFUSE;
2997         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2998                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2999         if (r_shadow_usingshadowmap2d)
3000         {
3001                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3002                 if (r_shadow_shadowmapvsdct)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3004
3005                 if (r_shadow_shadowmapsampler)
3006                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3007                 if (r_shadow_shadowmappcf > 1)
3008                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3009                 else if (r_shadow_shadowmappcf)
3010                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3011         }
3012         if (vid.allowalphatocoverage)
3013                 GL_AlphaToCoverage(false);
3014         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3015         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3016         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3017         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3018         switch(vid.renderpath)
3019         {
3020         case RENDERPATH_D3D9:
3021 #ifdef SUPPORTD3D
3022                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3024                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3028                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3029                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3030                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3031                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3033
3034                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3035                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3036                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3037                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3038                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3039                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3040 #endif
3041                 break;
3042         case RENDERPATH_D3D10:
3043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3044                 break;
3045         case RENDERPATH_D3D11:
3046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3047                 break;
3048         case RENDERPATH_GL20:
3049         case RENDERPATH_GLES2:
3050                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3051                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3052                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3053                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3054                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3055                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3056                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3057                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3058                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3059                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3060                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3061
3062                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3063                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3064                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3065                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3066                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3067                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3068                 break;
3069         case RENDERPATH_GL11:
3070         case RENDERPATH_GL13:
3071         case RENDERPATH_GLES1:
3072                 break;
3073         case RENDERPATH_SOFT:
3074                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3076                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3081                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3082                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3083                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3084                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3085
3086                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3087                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3088                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3089                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3090                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3091                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3092                 break;
3093         }
3094 }
3095
3096 #define SKINFRAME_HASH 1024
3097
3098 typedef struct
3099 {
3100         int loadsequence; // incremented each level change
3101         memexpandablearray_t array;
3102         skinframe_t *hash[SKINFRAME_HASH];
3103 }
3104 r_skinframe_t;
3105 r_skinframe_t r_skinframe;
3106
3107 void R_SkinFrame_PrepareForPurge(void)
3108 {
3109         r_skinframe.loadsequence++;
3110         // wrap it without hitting zero
3111         if (r_skinframe.loadsequence >= 200)
3112                 r_skinframe.loadsequence = 1;
3113 }
3114
3115 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3116 {
3117         if (!skinframe)
3118                 return;
3119         // mark the skinframe as used for the purging code
3120         skinframe->loadsequence = r_skinframe.loadsequence;
3121 }
3122
3123 void R_SkinFrame_Purge(void)
3124 {
3125         int i;
3126         skinframe_t *s;
3127         for (i = 0;i < SKINFRAME_HASH;i++)
3128         {
3129                 for (s = r_skinframe.hash[i];s;s = s->next)
3130                 {
3131                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3132                         {
3133                                 if (s->merged == s->base)
3134                                         s->merged = NULL;
3135                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3136                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3137                                 R_PurgeTexture(s->merged);s->merged = NULL;
3138                                 R_PurgeTexture(s->base  );s->base   = NULL;
3139                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3140                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3141                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3142                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3143                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3144                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3145                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3146                                 s->loadsequence = 0;
3147                         }
3148                 }
3149         }
3150 }
3151
3152 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3153         skinframe_t *item;
3154         char basename[MAX_QPATH];
3155
3156         Image_StripImageExtension(name, basename, sizeof(basename));
3157
3158         if( last == NULL ) {
3159                 int hashindex;
3160                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3161                 item = r_skinframe.hash[hashindex];
3162         } else {
3163                 item = last->next;
3164         }
3165
3166         // linearly search through the hash bucket
3167         for( ; item ; item = item->next ) {
3168                 if( !strcmp( item->basename, basename ) ) {
3169                         return item;
3170                 }
3171         }
3172         return NULL;
3173 }
3174
3175 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3176 {
3177         skinframe_t *item;
3178         int hashindex;
3179         char basename[MAX_QPATH];
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3185                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3186                         break;
3187
3188         if (!item) {
3189                 rtexture_t *dyntexture;
3190                 // check whether its a dynamic texture
3191                 dyntexture = CL_GetDynTexture( basename );
3192                 if (!add && !dyntexture)
3193                         return NULL;
3194                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3195                 memset(item, 0, sizeof(*item));
3196                 strlcpy(item->basename, basename, sizeof(item->basename));
3197                 item->base = dyntexture; // either NULL or dyntexture handle
3198                 item->textureflags = textureflags;
3199                 item->comparewidth = comparewidth;
3200                 item->compareheight = compareheight;
3201                 item->comparecrc = comparecrc;
3202                 item->next = r_skinframe.hash[hashindex];
3203                 r_skinframe.hash[hashindex] = item;
3204         }
3205         else if( item->base == NULL )
3206         {
3207                 rtexture_t *dyntexture;
3208                 // check whether its a dynamic texture
3209                 // 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]
3210                 dyntexture = CL_GetDynTexture( basename );
3211                 item->base = dyntexture; // either NULL or dyntexture handle
3212         }
3213
3214         R_SkinFrame_MarkUsed(item);
3215         return item;
3216 }
3217
3218 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3219         { \
3220                 unsigned long long avgcolor[5], wsum; \
3221                 int pix, comp, w; \
3222                 avgcolor[0] = 0; \
3223                 avgcolor[1] = 0; \
3224                 avgcolor[2] = 0; \
3225                 avgcolor[3] = 0; \
3226                 avgcolor[4] = 0; \
3227                 wsum = 0; \
3228                 for(pix = 0; pix < cnt; ++pix) \
3229                 { \
3230                         w = 0; \
3231                         for(comp = 0; comp < 3; ++comp) \
3232                                 w += getpixel; \
3233                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3234                         { \
3235                                 ++wsum; \
3236                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3237                                 w = getpixel; \
3238                                 for(comp = 0; comp < 3; ++comp) \
3239                                         avgcolor[comp] += getpixel * w; \
3240                                 avgcolor[3] += w; \
3241                         } \
3242                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3243                         avgcolor[4] += getpixel; \
3244                 } \
3245                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3246                         avgcolor[3] = 1; \
3247                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3248                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3249                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3250                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3251         }
3252
3253 extern cvar_t gl_picmip;
3254 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3255 {
3256         int j;
3257         unsigned char *pixels;
3258         unsigned char *bumppixels;
3259         unsigned char *basepixels = NULL;
3260         int basepixels_width = 0;
3261         int basepixels_height = 0;
3262         skinframe_t *skinframe;
3263         rtexture_t *ddsbase = NULL;
3264         qboolean ddshasalpha = false;
3265         float ddsavgcolor[4];
3266         char basename[MAX_QPATH];
3267         int miplevel = R_PicmipForFlags(textureflags);
3268         int savemiplevel = miplevel;
3269         int mymiplevel;
3270
3271         if (cls.state == ca_dedicated)
3272                 return NULL;
3273
3274         // return an existing skinframe if already loaded
3275         // if loading of the first image fails, don't make a new skinframe as it
3276         // would cause all future lookups of this to be missing
3277         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3278         if (skinframe && skinframe->base)
3279                 return skinframe;
3280
3281         Image_StripImageExtension(name, basename, sizeof(basename));
3282
3283         // check for DDS texture file first
3284         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3285         {
3286                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3287                 if (basepixels == NULL)
3288                         return NULL;
3289         }
3290
3291         // FIXME handle miplevel
3292
3293         if (developer_loading.integer)
3294                 Con_Printf("loading skin \"%s\"\n", name);
3295
3296         // we've got some pixels to store, so really allocate this new texture now
3297         if (!skinframe)
3298                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3299         skinframe->stain = NULL;
3300         skinframe->merged = NULL;
3301         skinframe->base = NULL;
3302         skinframe->pants = NULL;
3303         skinframe->shirt = NULL;
3304         skinframe->nmap = NULL;
3305         skinframe->gloss = NULL;
3306         skinframe->glow = NULL;
3307         skinframe->fog = NULL;
3308         skinframe->reflect = NULL;
3309         skinframe->hasalpha = false;
3310
3311         if (ddsbase)
3312         {
3313                 skinframe->base = ddsbase;
3314                 skinframe->hasalpha = ddshasalpha;
3315                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3316                 if (r_loadfog && skinframe->hasalpha)
3317                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3318                 //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]);
3319         }
3320         else
3321         {
3322                 basepixels_width = image_width;
3323                 basepixels_height = image_height;
3324                 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);
3325                 if (textureflags & TEXF_ALPHA)
3326                 {
3327                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3328                         {
3329                                 if (basepixels[j] < 255)
3330                                 {
3331                                         skinframe->hasalpha = true;
3332                                         break;
3333                                 }
3334                         }
3335                         if (r_loadfog && skinframe->hasalpha)
3336                         {
3337                                 // has transparent pixels
3338                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3339                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3340                                 {
3341                                         pixels[j+0] = 255;
3342                                         pixels[j+1] = 255;
3343                                         pixels[j+2] = 255;
3344                                         pixels[j+3] = basepixels[j+3];
3345                                 }
3346                                 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);
3347                                 Mem_Free(pixels);
3348                         }
3349                 }
3350                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3351                 //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]);
3352                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3353                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3354                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3355                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3356         }
3357
3358         if (r_loaddds)
3359         {
3360                 mymiplevel = savemiplevel;
3361                 if (r_loadnormalmap)
3362                         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);
3363                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3364                 if (r_loadgloss)
3365                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3366                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3367                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3368                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3369         }
3370
3371         // _norm is the name used by tenebrae and has been adopted as standard
3372         if (r_loadnormalmap && skinframe->nmap == NULL)
3373         {
3374                 mymiplevel = savemiplevel;
3375                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3376                 {
3377                         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);
3378                         Mem_Free(pixels);
3379                         pixels = NULL;
3380                 }
3381                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3382                 {
3383                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3384                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3385                         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);
3386                         Mem_Free(pixels);
3387                         Mem_Free(bumppixels);
3388                 }
3389                 else if (r_shadow_bumpscale_basetexture.value > 0)
3390                 {
3391                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3392                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3393                         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);
3394                         Mem_Free(pixels);
3395                 }
3396                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3397                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3398         }
3399
3400         // _luma is supported only for tenebrae compatibility
3401         // _glow is the preferred name
3402         mymiplevel = savemiplevel;
3403         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))))
3404         {
3405                 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);
3406                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3407                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3408                 Mem_Free(pixels);pixels = NULL;
3409         }
3410
3411         mymiplevel = savemiplevel;
3412         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3413         {
3414                 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);
3415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3416                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3417                 Mem_Free(pixels);
3418                 pixels = NULL;
3419         }
3420
3421         mymiplevel = savemiplevel;
3422         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3423         {
3424                 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);
3425                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3426                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3427                 Mem_Free(pixels);
3428                 pixels = NULL;
3429         }
3430
3431         mymiplevel = savemiplevel;
3432         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3433         {
3434                 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);
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3436                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3437                 Mem_Free(pixels);
3438                 pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 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);
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3446                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447                 Mem_Free(pixels);
3448                 pixels = NULL;
3449         }
3450
3451         if (basepixels)
3452                 Mem_Free(basepixels);
3453
3454         return skinframe;
3455 }
3456
3457 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3458 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3459 {
3460         int i;
3461         unsigned char *temp1, *temp2;
3462         skinframe_t *skinframe;
3463
3464         if (cls.state == ca_dedicated)
3465                 return NULL;
3466
3467         // if already loaded just return it, otherwise make a new skinframe
3468         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3469         if (skinframe && skinframe->base)
3470                 return skinframe;
3471
3472         skinframe->stain = NULL;
3473         skinframe->merged = NULL;
3474         skinframe->base = NULL;
3475         skinframe->pants = NULL;
3476         skinframe->shirt = NULL;
3477         skinframe->nmap = NULL;
3478         skinframe->gloss = NULL;
3479         skinframe->glow = NULL;
3480         skinframe->fog = NULL;
3481         skinframe->reflect = NULL;
3482         skinframe->hasalpha = false;
3483
3484         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3485         if (!skindata)
3486                 return NULL;
3487
3488         if (developer_loading.integer)
3489                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3490
3491         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3492         {
3493                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3494                 temp2 = temp1 + width * height * 4;
3495                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3496                 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);
3497                 Mem_Free(temp1);
3498         }
3499         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3500         if (textureflags & TEXF_ALPHA)
3501         {
3502                 for (i = 3;i < width * height * 4;i += 4)
3503                 {
3504                         if (skindata[i] < 255)
3505                         {
3506                                 skinframe->hasalpha = true;
3507                                 break;
3508                         }
3509                 }
3510                 if (r_loadfog && skinframe->hasalpha)
3511                 {
3512                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3513                         memcpy(fogpixels, skindata, width * height * 4);
3514                         for (i = 0;i < width * height * 4;i += 4)
3515                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3516                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3517                         Mem_Free(fogpixels);
3518                 }
3519         }
3520
3521         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3522         //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]);
3523
3524         return skinframe;
3525 }
3526
3527 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3528 {
3529         int i;
3530         int featuresmask;
3531         skinframe_t *skinframe;
3532
3533         if (cls.state == ca_dedicated)
3534                 return NULL;
3535
3536         // if already loaded just return it, otherwise make a new skinframe
3537         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3538         if (skinframe && skinframe->base)
3539                 return skinframe;
3540
3541         skinframe->stain = NULL;
3542         skinframe->merged = NULL;
3543         skinframe->base = NULL;
3544         skinframe->pants = NULL;
3545         skinframe->shirt = NULL;
3546         skinframe->nmap = NULL;
3547         skinframe->gloss = NULL;
3548         skinframe->glow = NULL;
3549         skinframe->fog = NULL;
3550         skinframe->reflect = NULL;
3551         skinframe->hasalpha = false;
3552
3553         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3554         if (!skindata)
3555                 return NULL;
3556
3557         if (developer_loading.integer)
3558                 Con_Printf("loading quake skin \"%s\"\n", name);
3559
3560         // 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)
3561         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3562         memcpy(skinframe->qpixels, skindata, width*height);
3563         skinframe->qwidth = width;
3564         skinframe->qheight = height;
3565
3566         featuresmask = 0;
3567         for (i = 0;i < width * height;i++)
3568                 featuresmask |= palette_featureflags[skindata[i]];
3569
3570         skinframe->hasalpha = false;
3571         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3572         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3573         skinframe->qgeneratemerged = true;
3574         skinframe->qgeneratebase = skinframe->qhascolormapping;
3575         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3576
3577         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3578         //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]);
3579
3580         return skinframe;
3581 }
3582
3583 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3584 {
3585         int width;
3586         int height;
3587         unsigned char *skindata;
3588
3589         if (!skinframe->qpixels)
3590                 return;
3591
3592         if (!skinframe->qhascolormapping)
3593                 colormapped = false;
3594
3595         if (colormapped)
3596         {
3597                 if (!skinframe->qgeneratebase)
3598                         return;
3599         }
3600         else
3601         {
3602                 if (!skinframe->qgeneratemerged)
3603                         return;
3604         }
3605
3606         width = skinframe->qwidth;
3607         height = skinframe->qheight;
3608         skindata = skinframe->qpixels;
3609
3610         if (skinframe->qgeneratenmap)
3611         {
3612                 unsigned char *temp1, *temp2;
3613                 skinframe->qgeneratenmap = false;
3614                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3615                 temp2 = temp1 + width * height * 4;
3616                 // use either a custom palette or the quake palette
3617                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3618                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3619                 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);
3620                 Mem_Free(temp1);
3621         }
3622
3623         if (skinframe->qgenerateglow)
3624         {
3625                 skinframe->qgenerateglow = false;
3626                 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
3627         }
3628
3629         if (colormapped)
3630         {
3631                 skinframe->qgeneratebase = false;
3632                 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);
3633                 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);
3634                 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);
3635         }
3636         else
3637         {
3638                 skinframe->qgeneratemerged = false;
3639                 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);
3640         }
3641
3642         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3643         {
3644                 Mem_Free(skinframe->qpixels);
3645                 skinframe->qpixels = NULL;
3646         }
3647 }
3648
3649 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)
3650 {
3651         int i;
3652         skinframe_t *skinframe;
3653
3654         if (cls.state == ca_dedicated)
3655                 return NULL;
3656
3657         // if already loaded just return it, otherwise make a new skinframe
3658         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3659         if (skinframe && skinframe->base)
3660                 return skinframe;
3661
3662         skinframe->stain = NULL;
3663         skinframe->merged = NULL;
3664         skinframe->base = NULL;
3665         skinframe->pants = NULL;
3666         skinframe->shirt = NULL;
3667         skinframe->nmap = NULL;
3668         skinframe->gloss = NULL;
3669         skinframe->glow = NULL;
3670         skinframe->fog = NULL;
3671         skinframe->reflect = NULL;
3672         skinframe->hasalpha = false;
3673
3674         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3675         if (!skindata)
3676                 return NULL;
3677
3678         if (developer_loading.integer)
3679                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3680
3681         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3682         if (textureflags & TEXF_ALPHA)
3683         {
3684                 for (i = 0;i < width * height;i++)
3685                 {
3686                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3687                         {
3688                                 skinframe->hasalpha = true;
3689                                 break;
3690                         }
3691                 }
3692                 if (r_loadfog && skinframe->hasalpha)
3693                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3694         }
3695
3696         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3697         //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]);
3698
3699         return skinframe;
3700 }
3701
3702 skinframe_t *R_SkinFrame_LoadMissing(void)
3703 {
3704         skinframe_t *skinframe;
3705
3706         if (cls.state == ca_dedicated)
3707                 return NULL;
3708
3709         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3710         skinframe->stain = NULL;
3711         skinframe->merged = NULL;
3712         skinframe->base = NULL;
3713         skinframe->pants = NULL;
3714         skinframe->shirt = NULL;
3715         skinframe->nmap = NULL;
3716         skinframe->gloss = NULL;
3717         skinframe->glow = NULL;
3718         skinframe->fog = NULL;
3719         skinframe->reflect = NULL;
3720         skinframe->hasalpha = false;
3721
3722         skinframe->avgcolor[0] = rand() / RAND_MAX;
3723         skinframe->avgcolor[1] = rand() / RAND_MAX;
3724         skinframe->avgcolor[2] = rand() / RAND_MAX;
3725         skinframe->avgcolor[3] = 1;
3726
3727         return skinframe;
3728 }
3729
3730 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3731 typedef struct suffixinfo_s
3732 {
3733         const char *suffix;
3734         qboolean flipx, flipy, flipdiagonal;
3735 }
3736 suffixinfo_t;
3737 static suffixinfo_t suffix[3][6] =
3738 {
3739         {
3740                 {"px",   false, false, false},
3741                 {"nx",   false, false, false},
3742                 {"py",   false, false, false},
3743                 {"ny",   false, false, false},
3744                 {"pz",   false, false, false},
3745                 {"nz",   false, false, false}
3746         },
3747         {
3748                 {"posx", false, false, false},
3749                 {"negx", false, false, false},
3750                 {"posy", false, false, false},
3751                 {"negy", false, false, false},
3752                 {"posz", false, false, false},
3753                 {"negz", false, false, false}
3754         },
3755         {
3756                 {"rt",    true, false,  true},
3757                 {"lf",   false,  true,  true},
3758                 {"ft",    true,  true, false},
3759                 {"bk",   false, false, false},
3760                 {"up",    true, false,  true},
3761                 {"dn",    true, false,  true}
3762         }
3763 };
3764
3765 static int componentorder[4] = {0, 1, 2, 3};
3766
3767 rtexture_t *R_LoadCubemap(const char *basename)
3768 {
3769         int i, j, cubemapsize;
3770         unsigned char *cubemappixels, *image_buffer;
3771         rtexture_t *cubemaptexture;
3772         char name[256];
3773         // must start 0 so the first loadimagepixels has no requested width/height
3774         cubemapsize = 0;
3775         cubemappixels = NULL;
3776         cubemaptexture = NULL;
3777         // keep trying different suffix groups (posx, px, rt) until one loads
3778         for (j = 0;j < 3 && !cubemappixels;j++)
3779         {
3780                 // load the 6 images in the suffix group
3781                 for (i = 0;i < 6;i++)
3782                 {
3783                         // generate an image name based on the base and and suffix
3784                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3785                         // load it
3786                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3787                         {
3788                                 // an image loaded, make sure width and height are equal
3789                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3790                                 {
3791                                         // if this is the first image to load successfully, allocate the cubemap memory
3792                                         if (!cubemappixels && image_width >= 1)
3793                                         {
3794                                                 cubemapsize = image_width;
3795                                                 // note this clears to black, so unavailable sides are black
3796                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3797                                         }
3798                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3799                                         if (cubemappixels)
3800                                                 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);
3801                                 }
3802                                 else
3803                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3804                                 // free the image
3805                                 Mem_Free(image_buffer);
3806                         }
3807                 }
3808         }
3809         // if a cubemap loaded, upload it
3810         if (cubemappixels)
3811         {
3812                 if (developer_loading.integer)
3813                         Con_Printf("loading cubemap \"%s\"\n", basename);
3814
3815                 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);
3816                 Mem_Free(cubemappixels);
3817         }
3818         else
3819         {
3820                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3821                 if (developer_loading.integer)
3822                 {
3823                         Con_Printf("(tried tried images ");
3824                         for (j = 0;j < 3;j++)
3825                                 for (i = 0;i < 6;i++)
3826                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3827                         Con_Print(" and was unable to find any of them).\n");
3828                 }
3829         }
3830         return cubemaptexture;
3831 }
3832
3833 rtexture_t *R_GetCubemap(const char *basename)
3834 {
3835         int i;
3836         for (i = 0;i < r_texture_numcubemaps;i++)
3837                 if (r_texture_cubemaps[i] != NULL)
3838                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3839                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3840         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3841                 return r_texture_whitecube;
3842         r_texture_numcubemaps++;
3843         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3844         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3845         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3846         return r_texture_cubemaps[i]->texture;
3847 }
3848
3849 void R_FreeCubemap(const char *basename)
3850 {
3851         int i;
3852
3853         for (i = 0;i < r_texture_numcubemaps;i++)
3854         {
3855                 if (r_texture_cubemaps[i] != NULL)
3856                 {
3857                         if (r_texture_cubemaps[i]->texture)
3858                         {
3859                                 if (developer_loading.integer)
3860                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3861                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3862                                 Mem_Free(r_texture_cubemaps[i]);
3863                                 r_texture_cubemaps[i] = NULL;
3864                         }
3865                 }
3866         }
3867 }
3868
3869 void R_FreeCubemaps(void)
3870 {
3871         int i;
3872         for (i = 0;i < r_texture_numcubemaps;i++)
3873         {
3874                 if (developer_loading.integer)
3875                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3876                 if (r_texture_cubemaps[i] != NULL)
3877                 {
3878                         if (r_texture_cubemaps[i]->texture)
3879                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3880                         Mem_Free(r_texture_cubemaps[i]);
3881                 }
3882         }
3883         r_texture_numcubemaps = 0;
3884 }
3885
3886 void R_Main_FreeViewCache(void)
3887 {
3888         if (r_refdef.viewcache.entityvisible)
3889                 Mem_Free(r_refdef.viewcache.entityvisible);
3890         if (r_refdef.viewcache.world_pvsbits)
3891                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3892         if (r_refdef.viewcache.world_leafvisible)
3893                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3894         if (r_refdef.viewcache.world_surfacevisible)
3895                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3896         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3897 }
3898
3899 void R_Main_ResizeViewCache(void)
3900 {
3901         int numentities = r_refdef.scene.numentities;
3902         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3903         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3904         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3905         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3906         if (r_refdef.viewcache.maxentities < numentities)
3907         {
3908                 r_refdef.viewcache.maxentities = numentities;
3909                 if (r_refdef.viewcache.entityvisible)
3910                         Mem_Free(r_refdef.viewcache.entityvisible);
3911                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3912         }
3913         if (r_refdef.viewcache.world_numclusters != numclusters)
3914         {
3915                 r_refdef.viewcache.world_numclusters = numclusters;
3916                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3917                 if (r_refdef.viewcache.world_pvsbits)
3918                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3919                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3920         }
3921         if (r_refdef.viewcache.world_numleafs != numleafs)
3922         {
3923                 r_refdef.viewcache.world_numleafs = numleafs;
3924                 if (r_refdef.viewcache.world_leafvisible)
3925                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3926                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3927         }
3928         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3929         {
3930                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3931                 if (r_refdef.viewcache.world_surfacevisible)
3932                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3933                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3934         }
3935 }
3936
3937 extern rtexture_t *loadingscreentexture;
3938 void gl_main_start(void)
3939 {
3940         loadingscreentexture = NULL;
3941         r_texture_blanknormalmap = NULL;
3942         r_texture_white = NULL;
3943         r_texture_grey128 = NULL;
3944         r_texture_black = NULL;
3945         r_texture_whitecube = NULL;
3946         r_texture_normalizationcube = NULL;
3947         r_texture_fogattenuation = NULL;
3948         r_texture_fogheighttexture = NULL;
3949         r_texture_gammaramps = NULL;
3950         r_texture_numcubemaps = 0;
3951
3952         r_loaddds = r_texture_dds_load.integer != 0;
3953         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3954
3955         switch(vid.renderpath)
3956         {
3957         case RENDERPATH_GL20:
3958         case RENDERPATH_D3D9:
3959         case RENDERPATH_D3D10:
3960         case RENDERPATH_D3D11:
3961         case RENDERPATH_SOFT:
3962         case RENDERPATH_GLES2:
3963                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3964                 Cvar_SetValueQuick(&gl_combine, 1);
3965                 Cvar_SetValueQuick(&r_glsl, 1);
3966                 r_loadnormalmap = true;
3967                 r_loadgloss = true;
3968                 r_loadfog = false;
3969                 break;
3970         case RENDERPATH_GL13:
3971         case RENDERPATH_GLES1:
3972                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3973                 Cvar_SetValueQuick(&gl_combine, 1);
3974                 Cvar_SetValueQuick(&r_glsl, 0);
3975                 r_loadnormalmap = false;
3976                 r_loadgloss = false;
3977                 r_loadfog = true;
3978                 break;
3979         case RENDERPATH_GL11:
3980                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3981                 Cvar_SetValueQuick(&gl_combine, 0);
3982                 Cvar_SetValueQuick(&r_glsl, 0);
3983                 r_loadnormalmap = false;
3984                 r_loadgloss = false;
3985                 r_loadfog = true;
3986                 break;
3987         }
3988
3989         R_AnimCache_Free();
3990         R_FrameData_Reset();
3991
3992         r_numqueries = 0;
3993         r_maxqueries = 0;
3994         memset(r_queries, 0, sizeof(r_queries));
3995
3996         r_qwskincache = NULL;
3997         r_qwskincache_size = 0;
3998
3999         // due to caching of texture_t references, the collision cache must be reset
4000         Collision_Cache_Reset(true);
4001
4002         // set up r_skinframe loading system for textures
4003         memset(&r_skinframe, 0, sizeof(r_skinframe));
4004         r_skinframe.loadsequence = 1;
4005         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4006
4007         r_main_texturepool = R_AllocTexturePool();
4008         R_BuildBlankTextures();
4009         R_BuildNoTexture();
4010         if (vid.support.arb_texture_cube_map)
4011         {
4012                 R_BuildWhiteCube();
4013                 R_BuildNormalizationCube();
4014         }
4015         r_texture_fogattenuation = NULL;
4016         r_texture_fogheighttexture = NULL;
4017         r_texture_gammaramps = NULL;
4018         //r_texture_fogintensity = NULL;
4019         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4020         memset(&r_waterstate, 0, sizeof(r_waterstate));
4021         r_glsl_permutation = NULL;
4022         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4023         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4024         glslshaderstring = NULL;
4025 #ifdef SUPPORTD3D
4026         r_hlsl_permutation = NULL;
4027         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4028         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4029 #endif
4030         hlslshaderstring = NULL;
4031         memset(&r_svbsp, 0, sizeof (r_svbsp));
4032
4033         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4034         r_texture_numcubemaps = 0;
4035
4036         r_refdef.fogmasktable_density = 0;
4037 }
4038
4039 void gl_main_shutdown(void)
4040 {
4041         R_AnimCache_Free();
4042         R_FrameData_Reset();
4043
4044         R_Main_FreeViewCache();
4045
4046         switch(vid.renderpath)
4047         {
4048         case RENDERPATH_GL11:
4049         case RENDERPATH_GL13:
4050         case RENDERPATH_GL20:
4051         case RENDERPATH_GLES1:
4052         case RENDERPATH_GLES2:
4053                 if (r_maxqueries)
4054                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4055                 break;
4056         case RENDERPATH_D3D9:
4057                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4058                 break;
4059         case RENDERPATH_D3D10:
4060                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4061                 break;
4062         case RENDERPATH_D3D11:
4063                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4064                 break;
4065         case RENDERPATH_SOFT:
4066                 break;
4067         }
4068
4069         r_numqueries = 0;
4070         r_maxqueries = 0;
4071         memset(r_queries, 0, sizeof(r_queries));
4072
4073         r_qwskincache = NULL;
4074         r_qwskincache_size = 0;
4075
4076         // clear out the r_skinframe state
4077         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4078         memset(&r_skinframe, 0, sizeof(r_skinframe));
4079
4080         if (r_svbsp.nodes)
4081                 Mem_Free(r_svbsp.nodes);
4082         memset(&r_svbsp, 0, sizeof (r_svbsp));
4083         R_FreeTexturePool(&r_main_texturepool);
4084         loadingscreentexture = NULL;
4085         r_texture_blanknormalmap = NULL;
4086         r_texture_white = NULL;
4087         r_texture_grey128 = NULL;
4088         r_texture_black = NULL;
4089         r_texture_whitecube = NULL;
4090         r_texture_normalizationcube = NULL;
4091         r_texture_fogattenuation = NULL;
4092         r_texture_fogheighttexture = NULL;
4093         r_texture_gammaramps = NULL;
4094         r_texture_numcubemaps = 0;
4095         //r_texture_fogintensity = NULL;
4096         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4097         memset(&r_waterstate, 0, sizeof(r_waterstate));
4098         R_GLSL_Restart_f();
4099
4100         r_glsl_permutation = NULL;
4101         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4102         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4103         glslshaderstring = NULL;
4104 #ifdef SUPPORTD3D
4105         r_hlsl_permutation = NULL;
4106         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4107         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4108 #endif
4109         hlslshaderstring = NULL;
4110 }
4111
4112 extern void CL_ParseEntityLump(char *entitystring);
4113 void gl_main_newmap(void)
4114 {
4115         // FIXME: move this code to client
4116         char *entities, entname[MAX_QPATH];
4117         if (r_qwskincache)
4118                 Mem_Free(r_qwskincache);
4119         r_qwskincache = NULL;
4120         r_qwskincache_size = 0;
4121         if (cl.worldmodel)
4122         {
4123                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4124                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4125                 {
4126                         CL_ParseEntityLump(entities);
4127                         Mem_Free(entities);
4128                         return;
4129                 }
4130                 if (cl.worldmodel->brush.entities)
4131                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4132         }
4133         R_Main_FreeViewCache();
4134
4135         R_FrameData_Reset();
4136 }
4137
4138 void GL_Main_Init(void)
4139 {
4140         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4141
4142         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4143         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4144         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4145         if (gamemode == GAME_NEHAHRA)
4146         {
4147                 Cvar_RegisterVariable (&gl_fogenable);
4148                 Cvar_RegisterVariable (&gl_fogdensity);
4149                 Cvar_RegisterVariable (&gl_fogred);
4150                 Cvar_RegisterVariable (&gl_foggreen);
4151                 Cvar_RegisterVariable (&gl_fogblue);
4152                 Cvar_RegisterVariable (&gl_fogstart);
4153                 Cvar_RegisterVariable (&gl_fogend);
4154                 Cvar_RegisterVariable (&gl_skyclip);
4155         }
4156         Cvar_RegisterVariable(&r_motionblur);
4157         Cvar_RegisterVariable(&r_damageblur);
4158         Cvar_RegisterVariable(&r_motionblur_averaging);
4159         Cvar_RegisterVariable(&r_motionblur_randomize);
4160         Cvar_RegisterVariable(&r_motionblur_minblur);
4161         Cvar_RegisterVariable(&r_motionblur_maxblur);
4162         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4163         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4164         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4165         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4166         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4167         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4168         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4169         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4170         Cvar_RegisterVariable(&r_equalize_entities_by);
4171         Cvar_RegisterVariable(&r_equalize_entities_to);
4172         Cvar_RegisterVariable(&r_depthfirst);
4173         Cvar_RegisterVariable(&r_useinfinitefarclip);
4174         Cvar_RegisterVariable(&r_farclip_base);
4175         Cvar_RegisterVariable(&r_farclip_world);
4176         Cvar_RegisterVariable(&r_nearclip);
4177         Cvar_RegisterVariable(&r_deformvertexes);
4178         Cvar_RegisterVariable(&r_transparent);
4179         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4180         Cvar_RegisterVariable(&r_showoverdraw);
4181         Cvar_RegisterVariable(&r_showbboxes);
4182         Cvar_RegisterVariable(&r_showsurfaces);
4183         Cvar_RegisterVariable(&r_showtris);
4184         Cvar_RegisterVariable(&r_shownormals);
4185         Cvar_RegisterVariable(&r_showlighting);
4186         Cvar_RegisterVariable(&r_showshadowvolumes);
4187         Cvar_RegisterVariable(&r_showcollisionbrushes);
4188         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4189         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4190         Cvar_RegisterVariable(&r_showdisabledepthtest);
4191         Cvar_RegisterVariable(&r_drawportals);
4192         Cvar_RegisterVariable(&r_drawentities);
4193         Cvar_RegisterVariable(&r_draw2d);
4194         Cvar_RegisterVariable(&r_drawworld);
4195         Cvar_RegisterVariable(&r_cullentities_trace);
4196         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4197         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4198         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4199         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4200         Cvar_RegisterVariable(&r_drawviewmodel);
4201         Cvar_RegisterVariable(&r_drawexteriormodel);
4202         Cvar_RegisterVariable(&r_speeds);
4203         Cvar_RegisterVariable(&r_fullbrights);
4204         Cvar_RegisterVariable(&r_wateralpha);
4205         Cvar_RegisterVariable(&r_dynamic);
4206         Cvar_RegisterVariable(&r_fakelight);
4207         Cvar_RegisterVariable(&r_fakelight_intensity);
4208         Cvar_RegisterVariable(&r_fullbright);
4209         Cvar_RegisterVariable(&r_shadows);
4210         Cvar_RegisterVariable(&r_shadows_darken);
4211         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4212         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4213         Cvar_RegisterVariable(&r_shadows_throwdistance);
4214         Cvar_RegisterVariable(&r_shadows_throwdirection);
4215         Cvar_RegisterVariable(&r_shadows_focus);
4216         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4217         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4218         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4219         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4220         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4221         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4222         Cvar_RegisterVariable(&r_fog_exp2);
4223         Cvar_RegisterVariable(&r_fog_clear);
4224         Cvar_RegisterVariable(&r_drawfog);
4225         Cvar_RegisterVariable(&r_transparentdepthmasking);
4226         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4227         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4228         Cvar_RegisterVariable(&r_texture_dds_load);
4229         Cvar_RegisterVariable(&r_texture_dds_save);
4230         Cvar_RegisterVariable(&r_textureunits);
4231         Cvar_RegisterVariable(&gl_combine);
4232         Cvar_RegisterVariable(&r_viewfbo);
4233         Cvar_RegisterVariable(&r_viewscale);
4234         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4235         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4236         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4237         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4238         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4239         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4240         Cvar_RegisterVariable(&r_glsl);
4241         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4242         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4243         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4244         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4245         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4246         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4247         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4248         Cvar_RegisterVariable(&r_glsl_postprocess);
4249         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4250         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4251         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4252         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4253         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4254         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4255         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4256         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4257
4258         Cvar_RegisterVariable(&r_water);
4259         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4260         Cvar_RegisterVariable(&r_water_clippingplanebias);
4261         Cvar_RegisterVariable(&r_water_refractdistort);
4262         Cvar_RegisterVariable(&r_water_reflectdistort);
4263         Cvar_RegisterVariable(&r_water_scissormode);
4264         Cvar_RegisterVariable(&r_water_lowquality);
4265
4266         Cvar_RegisterVariable(&r_lerpsprites);
4267         Cvar_RegisterVariable(&r_lerpmodels);
4268         Cvar_RegisterVariable(&r_lerplightstyles);
4269         Cvar_RegisterVariable(&r_waterscroll);
4270         Cvar_RegisterVariable(&r_bloom);
4271         Cvar_RegisterVariable(&r_bloom_colorscale);
4272         Cvar_RegisterVariable(&r_bloom_brighten);
4273         Cvar_RegisterVariable(&r_bloom_blur);
4274         Cvar_RegisterVariable(&r_bloom_resolution);
4275         Cvar_RegisterVariable(&r_bloom_colorexponent);
4276         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4277         Cvar_RegisterVariable(&r_hdr);
4278         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4279         Cvar_RegisterVariable(&r_hdr_glowintensity);
4280         Cvar_RegisterVariable(&r_hdr_range);
4281         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4282         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4283         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4284         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4285         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4286         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4287         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4288         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4289         Cvar_RegisterVariable(&developer_texturelogging);
4290         Cvar_RegisterVariable(&gl_lightmaps);
4291         Cvar_RegisterVariable(&r_test);
4292         Cvar_RegisterVariable(&r_glsl_saturation);
4293         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4294         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4295         Cvar_RegisterVariable(&r_framedatasize);
4296         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4297                 Cvar_SetValue("r_fullbrights", 0);
4298         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4299 }
4300
4301 extern void R_Textures_Init(void);
4302 extern void GL_Draw_Init(void);
4303 extern void GL_Main_Init(void);
4304 extern void R_Shadow_Init(void);
4305 extern void R_Sky_Init(void);
4306 extern void GL_Surf_Init(void);
4307 extern void R_Particles_Init(void);
4308 extern void R_Explosion_Init(void);
4309 extern void gl_backend_init(void);
4310 extern void Sbar_Init(void);
4311 extern void R_LightningBeams_Init(void);
4312 extern void Mod_RenderInit(void);
4313 extern void Font_Init(void);
4314
4315 void Render_Init(void)
4316 {
4317         gl_backend_init();
4318         R_Textures_Init();
4319         GL_Main_Init();
4320         Font_Init();
4321         GL_Draw_Init();
4322         R_Shadow_Init();
4323         R_Sky_Init();
4324         GL_Surf_Init();
4325         Sbar_Init();
4326         R_Particles_Init();
4327         R_Explosion_Init();
4328         R_LightningBeams_Init();
4329         Mod_RenderInit();
4330 }
4331
4332 /*
4333 ===============
4334 GL_Init
4335 ===============
4336 */
4337 extern char *ENGINE_EXTENSIONS;
4338 void GL_Init (void)
4339 {
4340         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4341         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4342         gl_version = (const char *)qglGetString(GL_VERSION);
4343         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4344
4345         if (!gl_extensions)
4346                 gl_extensions = "";
4347         if (!gl_platformextensions)
4348                 gl_platformextensions = "";
4349
4350         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4351         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4352         Con_Printf("GL_VERSION: %s\n", gl_version);
4353         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4354         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4355
4356         VID_CheckExtensions();
4357
4358         // LordHavoc: report supported extensions
4359         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4360
4361         // clear to black (loading plaque will be seen over this)
4362         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4363 }
4364
4365 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4366 {
4367         int i;
4368         mplane_t *p;
4369         if (r_trippy.integer)
4370                 return false;
4371         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4372         {
4373                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4374                 if (i == 4)
4375                         continue;
4376                 p = r_refdef.view.frustum + i;
4377                 switch(p->signbits)
4378                 {
4379                 default:
4380                 case 0:
4381                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 1:
4385                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 2:
4389                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 case 3:
4393                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 4:
4397                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 5:
4401                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 6:
4405                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 7:
4409                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 }
4413         }
4414         return false;
4415 }
4416
4417 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4418 {
4419         int i;
4420         const mplane_t *p;
4421         if (r_trippy.integer)
4422                 return false;
4423         for (i = 0;i < numplanes;i++)
4424         {
4425                 p = planes + i;
4426                 switch(p->signbits)
4427                 {
4428                 default:
4429                 case 0:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 1:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 2:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 3:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 4:
4446                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 5:
4450                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 6:
4454                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 7:
4458                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 }
4462         }
4463         return false;
4464 }
4465
4466 //==================================================================================
4467
4468 // LordHavoc: this stores temporary data used within the same frame
4469
4470 typedef struct r_framedata_mem_s
4471 {
4472         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4473         size_t size; // how much usable space
4474         size_t current; // how much space in use
4475         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4476         size_t wantedsize; // how much space was allocated
4477         unsigned char *data; // start of real data (16byte aligned)
4478 }
4479 r_framedata_mem_t;
4480
4481 static r_framedata_mem_t *r_framedata_mem;
4482
4483 void R_FrameData_Reset(void)
4484 {
4485         while (r_framedata_mem)
4486         {
4487                 r_framedata_mem_t *next = r_framedata_mem->purge;
4488                 Mem_Free(r_framedata_mem);
4489                 r_framedata_mem = next;
4490         }
4491 }
4492
4493 void R_FrameData_Resize(void)
4494 {
4495         size_t wantedsize;
4496         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4497         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4498         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4499         {
4500                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4501                 newmem->wantedsize = wantedsize;
4502                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4503                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4504                 newmem->current = 0;
4505                 newmem->mark = 0;
4506                 newmem->purge = r_framedata_mem;
4507                 r_framedata_mem = newmem;
4508         }
4509 }
4510
4511 void R_FrameData_NewFrame(void)
4512 {
4513         R_FrameData_Resize();
4514         if (!r_framedata_mem)
4515                 return;
4516         // if we ran out of space on the last frame, free the old memory now
4517         while (r_framedata_mem->purge)
4518         {
4519                 // repeatedly remove the second item in the list, leaving only head
4520                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4521                 Mem_Free(r_framedata_mem->purge);
4522                 r_framedata_mem->purge = next;
4523         }
4524         // reset the current mem pointer
4525         r_framedata_mem->current = 0;
4526         r_framedata_mem->mark = 0;
4527 }
4528
4529 void *R_FrameData_Alloc(size_t size)
4530 {
4531         void *data;
4532
4533         // align to 16 byte boundary - the data pointer is already aligned, so we
4534         // only need to ensure the size of every allocation is also aligned
4535         size = (size + 15) & ~15;
4536
4537         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4538         {
4539                 // emergency - we ran out of space, allocate more memory
4540                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4541                 R_FrameData_Resize();
4542         }
4543
4544         data = r_framedata_mem->data + r_framedata_mem->current;
4545         r_framedata_mem->current += size;
4546
4547         // count the usage for stats
4548         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4549         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4550
4551         return (void *)data;
4552 }
4553
4554 void *R_FrameData_Store(size_t size, void *data)
4555 {
4556         void *d = R_FrameData_Alloc(size);
4557         if (d && data)
4558                 memcpy(d, data, size);
4559         return d;
4560 }
4561
4562 void R_FrameData_SetMark(void)
4563 {
4564         if (!r_framedata_mem)
4565                 return;
4566         r_framedata_mem->mark = r_framedata_mem->current;
4567 }
4568
4569 void R_FrameData_ReturnToMark(void)
4570 {
4571         if (!r_framedata_mem)
4572                 return;
4573         r_framedata_mem->current = r_framedata_mem->mark;
4574 }
4575
4576 //==================================================================================
4577
4578 // LordHavoc: animcache originally written by Echon, rewritten since then
4579
4580 /**
4581  * Animation cache prevents re-generating mesh data for an animated model
4582  * multiple times in one frame for lighting, shadowing, reflections, etc.
4583  */
4584
4585 void R_AnimCache_Free(void)
4586 {
4587 }
4588
4589 void R_AnimCache_ClearCache(void)
4590 {
4591         int i;
4592         entity_render_t *ent;
4593
4594         for (i = 0;i < r_refdef.scene.numentities;i++)
4595         {
4596                 ent = r_refdef.scene.entities[i];
4597                 ent->animcache_vertex3f = NULL;
4598                 ent->animcache_normal3f = NULL;
4599                 ent->animcache_svector3f = NULL;
4600                 ent->animcache_tvector3f = NULL;
4601                 ent->animcache_vertexmesh = NULL;
4602                 ent->animcache_vertex3fbuffer = NULL;
4603                 ent->animcache_vertexmeshbuffer = NULL;
4604         }
4605 }
4606
4607 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4608 {
4609         int i;
4610
4611         // check if we need the meshbuffers
4612         if (!vid.useinterleavedarrays)
4613                 return;
4614
4615         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4616                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4617         // TODO: upload vertex3f buffer?
4618         if (ent->animcache_vertexmesh)
4619         {
4620                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4621                 for (i = 0;i < numvertices;i++)
4622                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4623                 if (ent->animcache_svector3f)
4624                         for (i = 0;i < numvertices;i++)
4625                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4626                 if (ent->animcache_tvector3f)
4627                         for (i = 0;i < numvertices;i++)
4628                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4629                 if (ent->animcache_normal3f)
4630                         for (i = 0;i < numvertices;i++)
4631                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4632                 // TODO: upload vertexmeshbuffer?
4633         }
4634 }
4635
4636 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4637 {
4638         dp_model_t *model = ent->model;
4639         int numvertices;
4640         // see if it's already cached this frame
4641         if (ent->animcache_vertex3f)
4642         {
4643                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4644                 if (wantnormals || wanttangents)
4645                 {
4646                         if (ent->animcache_normal3f)
4647                                 wantnormals = false;
4648                         if (ent->animcache_svector3f)
4649                                 wanttangents = false;
4650                         if (wantnormals || wanttangents)
4651                         {
4652                                 numvertices = model->surfmesh.num_vertices;
4653                                 if (wantnormals)
4654                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4655                                 if (wanttangents)
4656                                 {
4657                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4659                                 }
4660                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4661                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4662                         }
4663                 }
4664         }
4665         else
4666         {
4667                 // see if this ent is worth caching
4668                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4669                         return false;
4670                 // get some memory for this entity and generate mesh data
4671                 numvertices = model->surfmesh.num_vertices;
4672                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                 if (wantnormals)
4674                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4675                 if (wanttangents)
4676                 {
4677                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4678                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4679                 }
4680                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4681                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4682         }
4683         return true;
4684 }
4685
4686 void R_AnimCache_CacheVisibleEntities(void)
4687 {
4688         int i;
4689         qboolean wantnormals = true;
4690         qboolean wanttangents = !r_showsurfaces.integer;
4691
4692         switch(vid.renderpath)
4693         {
4694         case RENDERPATH_GL20:
4695         case RENDERPATH_D3D9:
4696         case RENDERPATH_D3D10:
4697         case RENDERPATH_D3D11:
4698         case RENDERPATH_GLES2:
4699                 break;
4700         case RENDERPATH_GL11:
4701         case RENDERPATH_GL13:
4702         case RENDERPATH_GLES1:
4703                 wanttangents = false;
4704                 break;
4705         case RENDERPATH_SOFT:
4706                 break;
4707         }
4708
4709         if (r_shownormals.integer)
4710                 wanttangents = wantnormals = true;
4711
4712         // TODO: thread this
4713         // NOTE: R_PrepareRTLights() also caches entities
4714
4715         for (i = 0;i < r_refdef.scene.numentities;i++)
4716                 if (r_refdef.viewcache.entityvisible[i])
4717                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4718 }
4719
4720 //==================================================================================
4721
4722 extern cvar_t r_overheadsprites_pushback;
4723
4724 static void R_View_UpdateEntityLighting (void)
4725 {
4726         int i;
4727         entity_render_t *ent;
4728         vec3_t tempdiffusenormal, avg;
4729         vec_t f, fa, fd, fdd;
4730         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4731
4732         for (i = 0;i < r_refdef.scene.numentities;i++)
4733         {
4734                 ent = r_refdef.scene.entities[i];
4735
4736                 // skip unseen models
4737                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4738                         continue;
4739
4740                 // skip bsp models
4741                 if (ent->model && ent->model->brush.num_leafs)
4742                 {
4743                         // TODO: use modellight for r_ambient settings on world?
4744                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4745                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4746                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4747                         continue;
4748                 }
4749
4750                 // fetch the lighting from the worldmodel data
4751                 VectorClear(ent->modellight_ambient);
4752                 VectorClear(ent->modellight_diffuse);
4753                 VectorClear(tempdiffusenormal);
4754                 if (ent->flags & RENDER_LIGHT)
4755                 {
4756                         vec3_t org;
4757                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4758
4759                         // complete lightning for lit sprites
4760                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4761                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4762                         {
4763                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4764                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4765                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4766                         }
4767                         else
4768                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4769
4770                         if(ent->flags & RENDER_EQUALIZE)
4771                         {
4772                                 // first fix up ambient lighting...
4773                                 if(r_equalize_entities_minambient.value > 0)
4774                                 {
4775                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4776                                         if(fd > 0)
4777                                         {
4778                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4779                                                 if(fa < r_equalize_entities_minambient.value * fd)
4780                                                 {
4781                                                         // solve:
4782                                                         //   fa'/fd' = minambient
4783                                                         //   fa'+0.25*fd' = fa+0.25*fd
4784                                                         //   ...
4785                                                         //   fa' = fd' * minambient
4786                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4787                                                         //   ...
4788                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4789                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4790                                                         //   ...
4791                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4792                                                         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
4793                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4794                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4795                                                 }
4796                                         }
4797                                 }
4798
4799                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4800                                 {
4801                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4802                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4803                                         f = fa + 0.25 * fd;
4804                                         if(f > 0)
4805                                         {
4806                                                 // adjust brightness and saturation to target
4807                                                 avg[0] = avg[1] = avg[2] = fa / f;
4808                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4809                                                 avg[0] = avg[1] = avg[2] = fd / f;
4810                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4811                                         }
4812                                 }
4813                         }
4814                 }
4815                 else // highly rare
4816                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4817
4818                 // move the light direction into modelspace coordinates for lighting code
4819                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4820                 if(VectorLength2(ent->modellight_lightdir) == 0)
4821                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4822                 VectorNormalize(ent->modellight_lightdir);
4823         }
4824 }
4825
4826 #define MAX_LINEOFSIGHTTRACES 64
4827
4828 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4829 {
4830         int i;
4831         vec3_t boxmins, boxmaxs;
4832         vec3_t start;
4833         vec3_t end;
4834         dp_model_t *model = r_refdef.scene.worldmodel;
4835
4836         if (!model || !model->brush.TraceLineOfSight)
4837                 return true;
4838
4839         // expand the box a little
4840         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4841         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4842         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4843         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4844         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4845         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4846
4847         // return true if eye is inside enlarged box
4848         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4849                 return true;
4850
4851         // try center
4852         VectorCopy(eye, start);
4853         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4854         if (model->brush.TraceLineOfSight(model, start, end))
4855                 return true;
4856
4857         // try various random positions
4858         for (i = 0;i < numsamples;i++)
4859         {
4860                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4861                 if (model->brush.TraceLineOfSight(model, start, end))
4862                         return true;
4863         }
4864
4865         return false;
4866 }
4867
4868
4869 static void R_View_UpdateEntityVisible (void)
4870 {
4871         int i;
4872         int renderimask;
4873         int samples;
4874         entity_render_t *ent;
4875
4876         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4877                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4878                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4879                 :                                                          RENDER_EXTERIORMODEL;
4880         if (!r_drawviewmodel.integer)
4881                 renderimask |= RENDER_VIEWMODEL;
4882         if (!r_drawexteriormodel.integer)
4883                 renderimask |= RENDER_EXTERIORMODEL;
4884         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4885         {
4886                 // worldmodel can check visibility
4887                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4888                 for (i = 0;i < r_refdef.scene.numentities;i++)
4889                 {
4890                         ent = r_refdef.scene.entities[i];
4891                         if (!(ent->flags & renderimask))
4892                         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)))
4893                         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))
4894                                 r_refdef.viewcache.entityvisible[i] = true;
4895                 }
4896         }
4897         else
4898         {
4899                 // no worldmodel or it can't check visibility
4900                 for (i = 0;i < r_refdef.scene.numentities;i++)
4901                 {
4902                         ent = r_refdef.scene.entities[i];
4903                         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));
4904                 }
4905         }
4906         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4907                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4908         {
4909                 for (i = 0;i < r_refdef.scene.numentities;i++)
4910                 {
4911                         if (!r_refdef.viewcache.entityvisible[i])
4912                                 continue;
4913                         ent = r_refdef.scene.entities[i];
4914                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4915                         {
4916                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4917                                 if (samples < 0)
4918                                         continue; // temp entities do pvs only
4919                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4920                                         ent->last_trace_visibility = realtime;
4921                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4922                                         r_refdef.viewcache.entityvisible[i] = 0;
4923                         }
4924                 }
4925         }
4926 }
4927
4928 /// only used if skyrendermasked, and normally returns false
4929 int R_DrawBrushModelsSky (void)
4930 {
4931         int i, sky;
4932         entity_render_t *ent;
4933
4934         sky = false;
4935         for (i = 0;i < r_refdef.scene.numentities;i++)
4936         {
4937                 if (!r_refdef.viewcache.entityvisible[i])
4938                         continue;
4939                 ent = r_refdef.scene.entities[i];
4940                 if (!ent->model || !ent->model->DrawSky)
4941                         continue;
4942                 ent->model->DrawSky(ent);
4943                 sky = true;
4944         }
4945         return sky;
4946 }
4947
4948 static void R_DrawNoModel(entity_render_t *ent);
4949 static void R_DrawModels(void)
4950 {
4951         int i;
4952         entity_render_t *ent;
4953
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 r_refdef.stats.entities++;
4960                 /*
4961                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4962                 {
4963                         vec3_t f, l, u, o;
4964                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4965                         Con_Printf("R_DrawModels\n");
4966                         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]);
4967                         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);
4968                         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);
4969                 }
4970                 */
4971                 if (ent->model && ent->model->Draw != NULL)
4972                         ent->model->Draw(ent);
4973                 else
4974                         R_DrawNoModel(ent);
4975         }
4976 }
4977
4978 static void R_DrawModelsDepth(void)
4979 {
4980         int i;
4981         entity_render_t *ent;
4982
4983         for (i = 0;i < r_refdef.scene.numentities;i++)
4984         {
4985                 if (!r_refdef.viewcache.entityvisible[i])
4986                         continue;
4987                 ent = r_refdef.scene.entities[i];
4988                 if (ent->model && ent->model->DrawDepth != NULL)
4989                         ent->model->DrawDepth(ent);
4990         }
4991 }
4992
4993 static void R_DrawModelsDebug(void)
4994 {
4995         int i;
4996         entity_render_t *ent;
4997
4998         for (i = 0;i < r_refdef.scene.numentities;i++)
4999         {
5000                 if (!r_refdef.viewcache.entityvisible[i])
5001                         continue;
5002                 ent = r_refdef.scene.entities[i];
5003                 if (ent->model && ent->model->DrawDebug != NULL)
5004                         ent->model->DrawDebug(ent);
5005         }
5006 }
5007
5008 static void R_DrawModelsAddWaterPlanes(void)
5009 {
5010         int i;
5011         entity_render_t *ent;
5012
5013         for (i = 0;i < r_refdef.scene.numentities;i++)
5014         {
5015                 if (!r_refdef.viewcache.entityvisible[i])
5016                         continue;
5017                 ent = r_refdef.scene.entities[i];
5018                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5019                         ent->model->DrawAddWaterPlanes(ent);
5020         }
5021 }
5022
5023 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5024 {
5025         if (r_hdr_irisadaptation.integer)
5026         {
5027                 vec3_t ambient;
5028                 vec3_t diffuse;
5029                 vec3_t diffusenormal;
5030                 vec_t brightness;
5031                 vec_t goal;
5032                 vec_t current;
5033                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5034                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5035                 brightness = max(0.0000001f, brightness);
5036                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5037                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5038                 current = r_hdr_irisadaptation_value.value;
5039                 if (current < goal)
5040                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5041                 else if (current > goal)
5042                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5043                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5044                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5045         }
5046         else if (r_hdr_irisadaptation_value.value != 1.0f)
5047                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5048 }
5049
5050 static void R_View_SetFrustum(const int *scissor)
5051 {
5052         int i;
5053         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5054         vec3_t forward, left, up, origin, v;
5055
5056         if(scissor)
5057         {
5058                 // flipped x coordinates (because x points left here)
5059                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5060                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5061
5062                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5063                 switch(vid.renderpath)
5064                 {
5065                         case RENDERPATH_D3D9:
5066                         case RENDERPATH_D3D10:
5067                         case RENDERPATH_D3D11:
5068                                 // non-flipped y coordinates
5069                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5070                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5071                                 break;
5072                         case RENDERPATH_SOFT:
5073                         case RENDERPATH_GL11:
5074                         case RENDERPATH_GL13:
5075                         case RENDERPATH_GL20:
5076                         case RENDERPATH_GLES1:
5077                         case RENDERPATH_GLES2:
5078                                 // non-flipped y coordinates
5079                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5080                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5081                                 break;
5082                 }
5083         }
5084
5085         // we can't trust r_refdef.view.forward and friends in reflected scenes
5086         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5087
5088 #if 0
5089         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5090         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5091         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5092         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5093         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5094         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5095         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5096         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5097         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5098         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5099         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5100         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5101 #endif
5102
5103 #if 0
5104         zNear = r_refdef.nearclip;
5105         nudge = 1.0 - 1.0 / (1<<23);
5106         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5107         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5108         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5109         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5110         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5111         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5112         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5113         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5114 #endif
5115
5116
5117
5118 #if 0
5119         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5120         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5121         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5122         r_refdef.view.frustum[0].dist = m[15] - m[12];
5123
5124         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5125         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5126         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5127         r_refdef.view.frustum[1].dist = m[15] + m[12];
5128
5129         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5130         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5131         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5132         r_refdef.view.frustum[2].dist = m[15] - m[13];
5133
5134         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5135         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5136         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5137         r_refdef.view.frustum[3].dist = m[15] + m[13];
5138
5139         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5140         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5141         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5142         r_refdef.view.frustum[4].dist = m[15] - m[14];
5143
5144         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5145         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5146         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5147         r_refdef.view.frustum[5].dist = m[15] + m[14];
5148 #endif
5149
5150         if (r_refdef.view.useperspective)
5151         {
5152                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5153                 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]);
5154                 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]);
5155                 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]);
5156                 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]);
5157
5158                 // then the normals from the corners relative to origin
5159                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5160                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5161                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5162                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5163
5164                 // in a NORMAL view, forward cross left == up
5165                 // in a REFLECTED view, forward cross left == down
5166                 // so our cross products above need to be adjusted for a left handed coordinate system
5167                 CrossProduct(forward, left, v);
5168                 if(DotProduct(v, up) < 0)
5169                 {
5170                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5171                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5172                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5173                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5174                 }
5175
5176                 // Leaving those out was a mistake, those were in the old code, and they
5177                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5178                 // I couldn't reproduce it after adding those normalizations. --blub
5179                 VectorNormalize(r_refdef.view.frustum[0].normal);
5180                 VectorNormalize(r_refdef.view.frustum[1].normal);
5181                 VectorNormalize(r_refdef.view.frustum[2].normal);
5182                 VectorNormalize(r_refdef.view.frustum[3].normal);
5183
5184                 // make the corners absolute
5185                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5186                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5187                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5188                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5189
5190                 // one more normal
5191                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5192
5193                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5194                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5195                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5196                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5197                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5198         }
5199         else
5200         {
5201                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5202                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5203                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5204                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5205                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5206                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5207                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5208                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5209                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5210                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5211         }
5212         r_refdef.view.numfrustumplanes = 5;
5213
5214         if (r_refdef.view.useclipplane)
5215         {
5216                 r_refdef.view.numfrustumplanes = 6;
5217                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5218         }
5219
5220         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5221                 PlaneClassify(r_refdef.view.frustum + i);
5222
5223         // LordHavoc: note to all quake engine coders, Quake had a special case
5224         // for 90 degrees which assumed a square view (wrong), so I removed it,
5225         // Quake2 has it disabled as well.
5226
5227         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5228         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5229         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5230         //PlaneClassify(&frustum[0]);
5231
5232         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5233         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5234         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5235         //PlaneClassify(&frustum[1]);
5236
5237         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5238         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5239         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5240         //PlaneClassify(&frustum[2]);
5241
5242         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5243         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5244         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5245         //PlaneClassify(&frustum[3]);
5246
5247         // nearclip plane
5248         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5249         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5250         //PlaneClassify(&frustum[4]);
5251 }
5252
5253 void R_View_UpdateWithScissor(const int *myscissor)
5254 {
5255         R_Main_ResizeViewCache();
5256         R_View_SetFrustum(myscissor);
5257         R_View_WorldVisibility(r_refdef.view.useclipplane);
5258         R_View_UpdateEntityVisible();
5259         R_View_UpdateEntityLighting();
5260 }
5261
5262 void R_View_Update(void)
5263 {
5264         R_Main_ResizeViewCache();
5265         R_View_SetFrustum(NULL);
5266         R_View_WorldVisibility(r_refdef.view.useclipplane);
5267         R_View_UpdateEntityVisible();
5268         R_View_UpdateEntityLighting();
5269 }
5270
5271 float viewscalefpsadjusted = 1.0f;
5272
5273 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5274 {
5275         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5276         scale = bound(0.03125f, scale, 1.0f);
5277         *outwidth = (int)ceil(width * scale);
5278         *outheight = (int)ceil(height * scale);
5279 }
5280
5281 void R_Mesh_SetMainRenderTargets(void)
5282 {
5283         if (r_bloomstate.fbo_framebuffer)
5284                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5285         else
5286                 R_Mesh_ResetRenderTargets();
5287 }
5288
5289 void R_SetupView(qboolean allowwaterclippingplane)
5290 {
5291         const float *customclipplane = NULL;
5292         float plane[4];
5293         int scaledwidth, scaledheight;
5294         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5295         {
5296                 // LordHavoc: couldn't figure out how to make this approach the
5297                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5298                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5299                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5300                         dist = r_refdef.view.clipplane.dist;
5301                 plane[0] = r_refdef.view.clipplane.normal[0];
5302                 plane[1] = r_refdef.view.clipplane.normal[1];
5303                 plane[2] = r_refdef.view.clipplane.normal[2];
5304                 plane[3] = -dist;
5305                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5306         }
5307
5308         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5309         if (!r_refdef.view.useperspective)
5310                 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);
5311         else if (vid.stencil && r_useinfinitefarclip.integer)
5312                 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);
5313         else
5314                 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);
5315         R_Mesh_SetMainRenderTargets();
5316         R_SetViewport(&r_refdef.view.viewport);
5317         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5318         {
5319                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5320                 float screenplane[4];
5321                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5322                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5323                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5324                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5325                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5326         }
5327 }
5328
5329 void R_EntityMatrix(const matrix4x4_t *matrix)
5330 {
5331         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5332         {
5333                 gl_modelmatrixchanged = false;
5334                 gl_modelmatrix = *matrix;
5335                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5336                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5337                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5338                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5339                 CHECKGLERROR
5340                 switch(vid.renderpath)
5341                 {
5342                 case RENDERPATH_D3D9:
5343 #ifdef SUPPORTD3D
5344                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5345                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5346 #endif
5347                         break;
5348                 case RENDERPATH_D3D10:
5349                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5350                         break;
5351                 case RENDERPATH_D3D11:
5352                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5353                         break;
5354                 case RENDERPATH_GL11:
5355                 case RENDERPATH_GL13:
5356                 case RENDERPATH_GLES1:
5357                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5358                         break;
5359                 case RENDERPATH_SOFT:
5360                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5361                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5362                         break;
5363                 case RENDERPATH_GL20:
5364                 case RENDERPATH_GLES2:
5365                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5366                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5367                         break;
5368                 }
5369         }
5370 }
5371
5372 void R_ResetViewRendering2D(void)
5373 {
5374         r_viewport_t viewport;
5375         DrawQ_Finish();
5376
5377         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5378         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);
5379         R_Mesh_ResetRenderTargets();
5380         R_SetViewport(&viewport);
5381         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5382         GL_Color(1, 1, 1, 1);
5383         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5384         GL_BlendFunc(GL_ONE, GL_ZERO);
5385         GL_ScissorTest(false);
5386         GL_DepthMask(false);
5387         GL_DepthRange(0, 1);
5388         GL_DepthTest(false);
5389         GL_DepthFunc(GL_LEQUAL);
5390         R_EntityMatrix(&identitymatrix);
5391         R_Mesh_ResetTextureState();
5392         GL_PolygonOffset(0, 0);
5393         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5394         switch(vid.renderpath)
5395         {
5396         case RENDERPATH_GL11:
5397         case RENDERPATH_GL13:
5398         case RENDERPATH_GL20:
5399         case RENDERPATH_GLES1:
5400         case RENDERPATH_GLES2:
5401                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5402                 break;
5403         case RENDERPATH_D3D9:
5404         case RENDERPATH_D3D10:
5405         case RENDERPATH_D3D11:
5406         case RENDERPATH_SOFT:
5407                 break;
5408         }
5409         GL_CullFace(GL_NONE);
5410 }
5411
5412 void R_ResetViewRendering3D(void)
5413 {
5414         DrawQ_Finish();
5415
5416         R_SetupView(true);
5417         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5418         GL_Color(1, 1, 1, 1);
5419         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5420         GL_BlendFunc(GL_ONE, GL_ZERO);
5421         GL_ScissorTest(true);
5422         GL_DepthMask(true);
5423         GL_DepthRange(0, 1);
5424         GL_DepthTest(true);
5425         GL_DepthFunc(GL_LEQUAL);
5426         R_EntityMatrix(&identitymatrix);
5427         R_Mesh_ResetTextureState();
5428         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5429         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5430         switch(vid.renderpath)
5431         {
5432         case RENDERPATH_GL11:
5433         case RENDERPATH_GL13:
5434         case RENDERPATH_GL20:
5435         case RENDERPATH_GLES1:
5436         case RENDERPATH_GLES2:
5437                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5438                 break;
5439         case RENDERPATH_D3D9:
5440         case RENDERPATH_D3D10:
5441         case RENDERPATH_D3D11:
5442         case RENDERPATH_SOFT:
5443                 break;
5444         }
5445         GL_CullFace(r_refdef.view.cullface_back);
5446 }
5447
5448 /*
5449 ================
5450 R_RenderView_UpdateViewVectors
5451 ================
5452 */
5453 static void R_RenderView_UpdateViewVectors(void)
5454 {
5455         // break apart the view matrix into vectors for various purposes
5456         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5457         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5458         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5459         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5460         // make an inverted copy of the view matrix for tracking sprites
5461         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5462 }
5463
5464 void R_RenderScene(void);
5465 void R_RenderWaterPlanes(void);
5466
5467 static void R_Water_StartFrame(void)
5468 {
5469         int i;
5470         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5471         r_waterstate_waterplane_t *p;
5472
5473         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5474                 return;
5475
5476         switch(vid.renderpath)
5477         {
5478         case RENDERPATH_GL20:
5479         case RENDERPATH_D3D9:
5480         case RENDERPATH_D3D10:
5481         case RENDERPATH_D3D11:
5482         case RENDERPATH_SOFT:
5483         case RENDERPATH_GLES2:
5484                 break;
5485         case RENDERPATH_GL11:
5486         case RENDERPATH_GL13:
5487         case RENDERPATH_GLES1:
5488                 return;
5489         }
5490
5491         // set waterwidth and waterheight to the water resolution that will be
5492         // used (often less than the screen resolution for faster rendering)
5493         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5494
5495         // calculate desired texture sizes
5496         // can't use water if the card does not support the texture size
5497         if (!r_water.integer || r_showsurfaces.integer)
5498                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5499         else if (vid.support.arb_texture_non_power_of_two)
5500         {
5501                 texturewidth = waterwidth;
5502                 textureheight = waterheight;
5503                 camerawidth = waterwidth;
5504                 cameraheight = waterheight;
5505         }
5506         else
5507         {
5508                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5509                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5510                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5511                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5512         }
5513
5514         // allocate textures as needed
5515         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5516         {
5517                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5518                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5519                 {
5520                         if (p->texture_refraction)
5521                                 R_FreeTexture(p->texture_refraction);
5522                         p->texture_refraction = NULL;
5523                         if (p->texture_reflection)
5524                                 R_FreeTexture(p->texture_reflection);
5525                         p->texture_reflection = NULL;
5526                         if (p->texture_camera)
5527                                 R_FreeTexture(p->texture_camera);
5528                         p->texture_camera = NULL;
5529                 }
5530                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5531                 r_waterstate.texturewidth = texturewidth;
5532                 r_waterstate.textureheight = textureheight;
5533                 r_waterstate.camerawidth = camerawidth;
5534                 r_waterstate.cameraheight = cameraheight;
5535         }
5536
5537         if (r_waterstate.texturewidth)
5538         {
5539                 int scaledwidth, scaledheight;
5540
5541                 r_waterstate.enabled = true;
5542
5543                 // when doing a reduced render (HDR) we want to use a smaller area
5544                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5545                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5546                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5547
5548                 // set up variables that will be used in shader setup
5549                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5550                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5551                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5552                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5553         }
5554
5555         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5556         r_waterstate.numwaterplanes = 0;
5557 }
5558
5559 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5560 {
5561         int triangleindex, planeindex;
5562         const int *e;
5563         vec3_t vert[3];
5564         vec3_t normal;
5565         vec3_t center;
5566         mplane_t plane;
5567         r_waterstate_waterplane_t *p;
5568         texture_t *t = R_GetCurrentTexture(surface->texture);
5569
5570         // just use the first triangle with a valid normal for any decisions
5571         VectorClear(normal);
5572         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5573         {
5574                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5575                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5576                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5577                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5578                 if (VectorLength2(normal) >= 0.001)
5579                         break;
5580         }
5581
5582         VectorCopy(normal, plane.normal);
5583         VectorNormalize(plane.normal);
5584         plane.dist = DotProduct(vert[0], plane.normal);
5585         PlaneClassify(&plane);
5586         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5587         {
5588                 // skip backfaces (except if nocullface is set)
5589                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5590                         return;
5591                 VectorNegate(plane.normal, plane.normal);
5592                 plane.dist *= -1;
5593                 PlaneClassify(&plane);
5594         }
5595
5596
5597         // find a matching plane if there is one
5598         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5599                 if(p->camera_entity == t->camera_entity)
5600                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5601                                 break;
5602         if (planeindex >= r_waterstate.maxwaterplanes)
5603                 return; // nothing we can do, out of planes
5604
5605         // if this triangle does not fit any known plane rendered this frame, add one
5606         if (planeindex >= r_waterstate.numwaterplanes)
5607         {
5608                 // store the new plane
5609                 r_waterstate.numwaterplanes++;
5610                 p->plane = plane;
5611                 // clear materialflags and pvs
5612                 p->materialflags = 0;
5613                 p->pvsvalid = false;
5614                 p->camera_entity = t->camera_entity;
5615                 VectorCopy(surface->mins, p->mins);
5616                 VectorCopy(surface->maxs, p->maxs);
5617         }
5618         else
5619         {
5620                 // merge mins/maxs
5621                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5622                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5623                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5624                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5625                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5626                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5627         }
5628         // merge this surface's materialflags into the waterplane
5629         p->materialflags |= t->currentmaterialflags;
5630         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5631         {
5632                 // merge this surface's PVS into the waterplane
5633                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5634                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5635                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5636                 {
5637                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5638                         p->pvsvalid = true;
5639                 }
5640         }
5641 }
5642
5643 extern cvar_t r_drawparticles;
5644 extern cvar_t r_drawdecals;
5645
5646 static void R_Water_ProcessPlanes(void)
5647 {
5648         int myscissor[4];
5649         r_refdef_view_t originalview;
5650         r_refdef_view_t myview;
5651         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;
5652         r_waterstate_waterplane_t *p;
5653         vec3_t visorigin;
5654
5655         originalview = r_refdef.view;
5656
5657         // lowquality hack, temporarily shut down some cvars and restore afterwards
5658         qualityreduction = r_water_lowquality.integer;
5659         if (qualityreduction > 0)
5660         {
5661                 if (qualityreduction >= 1)
5662                 {
5663                         old_r_shadows = r_shadows.integer;
5664                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5665                         old_r_dlight = r_shadow_realtime_dlight.integer;
5666                         Cvar_SetValueQuick(&r_shadows, 0);
5667                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5668                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5669                 }
5670                 if (qualityreduction >= 2)
5671                 {
5672                         old_r_dynamic = r_dynamic.integer;
5673                         old_r_particles = r_drawparticles.integer;
5674                         old_r_decals = r_drawdecals.integer;
5675                         Cvar_SetValueQuick(&r_dynamic, 0);
5676                         Cvar_SetValueQuick(&r_drawparticles, 0);
5677                         Cvar_SetValueQuick(&r_drawdecals, 0);
5678                 }
5679         }
5680
5681         // make sure enough textures are allocated
5682         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5683         {
5684                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5685                 {
5686                         if (!p->texture_refraction)
5687                                 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);
5688                         if (!p->texture_refraction)
5689                                 goto error;
5690                 }
5691                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5692                 {
5693                         if (!p->texture_camera)
5694                                 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);
5695                         if (!p->texture_camera)
5696                                 goto error;
5697                 }
5698
5699                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5700                 {
5701                         if (!p->texture_reflection)
5702                                 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);
5703                         if (!p->texture_reflection)
5704                                 goto error;
5705                 }
5706         }
5707
5708         // render views
5709         r_refdef.view = originalview;
5710         r_refdef.view.showdebug = false;
5711         r_refdef.view.width = r_waterstate.waterwidth;
5712         r_refdef.view.height = r_waterstate.waterheight;
5713         r_refdef.view.useclipplane = true;
5714         myview = r_refdef.view;
5715         r_waterstate.renderingscene = true;
5716         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5717         {
5718                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5719                 {
5720                         r_refdef.view = myview;
5721                         if(r_water_scissormode.integer)
5722                         {
5723                                 R_SetupView(true);
5724                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5725                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5726                         }
5727
5728                         // render reflected scene and copy into texture
5729                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5730                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5731                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5732                         r_refdef.view.clipplane = p->plane;
5733                         // reverse the cullface settings for this render
5734                         r_refdef.view.cullface_front = GL_FRONT;
5735                         r_refdef.view.cullface_back = GL_BACK;
5736                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5737                         {
5738                                 r_refdef.view.usecustompvs = true;
5739                                 if (p->pvsvalid)
5740                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5741                                 else
5742                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5743                         }
5744
5745                         R_ResetViewRendering3D();
5746                         R_ClearScreen(r_refdef.fogenabled);
5747                         if(r_water_scissormode.integer & 2)
5748                                 R_View_UpdateWithScissor(myscissor);
5749                         else
5750                                 R_View_Update();
5751                         if(r_water_scissormode.integer & 1)
5752                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5753                         R_RenderScene();
5754
5755                         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);
5756                 }
5757
5758                 // render the normal view scene and copy into texture
5759                 // (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)
5760                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5761                 {
5762                         r_refdef.view = myview;
5763                         if(r_water_scissormode.integer)
5764                         {
5765                                 R_SetupView(true);
5766                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5767                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5768                         }
5769
5770                         r_waterstate.renderingrefraction = true;
5771
5772                         r_refdef.view.clipplane = p->plane;
5773                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5774                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5775
5776                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5777                         {
5778                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5779                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5780                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5781                                 R_RenderView_UpdateViewVectors();
5782                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5783                                 {
5784                                         r_refdef.view.usecustompvs = true;
5785                                         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);
5786                                 }
5787                         }
5788
5789                         PlaneClassify(&r_refdef.view.clipplane);
5790
5791                         R_ResetViewRendering3D();
5792                         R_ClearScreen(r_refdef.fogenabled);
5793                         if(r_water_scissormode.integer & 2)
5794                                 R_View_UpdateWithScissor(myscissor);
5795                         else
5796                                 R_View_Update();
5797                         if(r_water_scissormode.integer & 1)
5798                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5799                         R_RenderScene();
5800
5801                         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);
5802                         r_waterstate.renderingrefraction = false;
5803                 }
5804                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5805                 {
5806                         r_refdef.view = myview;
5807
5808                         r_refdef.view.clipplane = p->plane;
5809                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5810                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5811
5812                         r_refdef.view.width = r_waterstate.camerawidth;
5813                         r_refdef.view.height = r_waterstate.cameraheight;
5814                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5815                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5816
5817                         if(p->camera_entity)
5818                         {
5819                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5820                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5821                         }
5822
5823                         // note: all of the view is used for displaying... so
5824                         // there is no use in scissoring
5825
5826                         // reverse the cullface settings for this render
5827                         r_refdef.view.cullface_front = GL_FRONT;
5828                         r_refdef.view.cullface_back = GL_BACK;
5829                         // also reverse the view matrix
5830                         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
5831                         R_RenderView_UpdateViewVectors();
5832                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5833                         {
5834                                 r_refdef.view.usecustompvs = true;
5835                                 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);
5836                         }
5837                         
5838                         // camera needs no clipplane
5839                         r_refdef.view.useclipplane = false;
5840
5841                         PlaneClassify(&r_refdef.view.clipplane);
5842
5843                         R_ResetViewRendering3D();
5844                         R_ClearScreen(r_refdef.fogenabled);
5845                         R_View_Update();
5846                         R_RenderScene();
5847
5848                         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);
5849                         r_waterstate.renderingrefraction = false;
5850                 }
5851
5852         }
5853         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5854         r_waterstate.renderingscene = false;
5855         r_refdef.view = originalview;
5856         R_ResetViewRendering3D();
5857         R_ClearScreen(r_refdef.fogenabled);
5858         R_View_Update();
5859         goto finish;
5860 error:
5861         r_refdef.view = originalview;
5862         r_waterstate.renderingscene = false;
5863         Cvar_SetValueQuick(&r_water, 0);
5864         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5865 finish:
5866         // lowquality hack, restore cvars
5867         if (qualityreduction > 0)
5868         {
5869                 if (qualityreduction >= 1)
5870                 {
5871                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5872                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5873                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5874                 }
5875                 if (qualityreduction >= 2)
5876                 {
5877                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5878                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5879                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5880                 }
5881         }
5882 }
5883
5884 void R_Bloom_StartFrame(void)
5885 {
5886         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5887         int viewwidth, viewheight;
5888         textype_t textype;
5889
5890         if (r_viewscale_fpsscaling.integer)
5891         {
5892                 double actualframetime;
5893                 double targetframetime;
5894                 double adjust;
5895                 actualframetime = r_refdef.lastdrawscreentime;
5896                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5897                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5898                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5899                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5900                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5901                 viewscalefpsadjusted += adjust;
5902                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5903         }
5904         else
5905                 viewscalefpsadjusted = 1.0f;
5906
5907         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5908
5909         switch(vid.renderpath)
5910         {
5911         case RENDERPATH_GL20:
5912         case RENDERPATH_D3D9:
5913         case RENDERPATH_D3D10:
5914         case RENDERPATH_D3D11:
5915         case RENDERPATH_SOFT:
5916         case RENDERPATH_GLES2:
5917                 break;
5918         case RENDERPATH_GL11:
5919         case RENDERPATH_GL13:
5920         case RENDERPATH_GLES1:
5921                 return;
5922         }
5923
5924         // set bloomwidth and bloomheight to the bloom resolution that will be
5925         // used (often less than the screen resolution for faster rendering)
5926         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5927         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5928         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5929         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5930         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5931
5932         // calculate desired texture sizes
5933         if (vid.support.arb_texture_non_power_of_two)
5934         {
5935                 screentexturewidth = vid.width;
5936                 screentextureheight = vid.height;
5937                 bloomtexturewidth = r_bloomstate.bloomwidth;
5938                 bloomtextureheight = r_bloomstate.bloomheight;
5939         }
5940         else
5941         {
5942                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5943                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5944                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5945                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5946         }
5947
5948         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))
5949         {
5950                 Cvar_SetValueQuick(&r_hdr, 0);
5951                 Cvar_SetValueQuick(&r_bloom, 0);
5952                 Cvar_SetValueQuick(&r_motionblur, 0);
5953                 Cvar_SetValueQuick(&r_damageblur, 0);
5954         }
5955
5956         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)
5957                 screentexturewidth = screentextureheight = 0;
5958         if (!r_hdr.integer && !r_bloom.integer)
5959                 bloomtexturewidth = bloomtextureheight = 0;
5960
5961         textype = TEXTYPE_COLORBUFFER;
5962         switch (vid.renderpath)
5963         {
5964         case RENDERPATH_GL20:
5965         case RENDERPATH_GLES2:
5966                 if (vid.support.ext_framebuffer_object)
5967                 {
5968                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5969                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5970                 }
5971                 break;
5972         case RENDERPATH_GL11:
5973         case RENDERPATH_GL13:
5974         case RENDERPATH_GLES1:
5975         case RENDERPATH_D3D9:
5976         case RENDERPATH_D3D10:
5977         case RENDERPATH_D3D11:
5978         case RENDERPATH_SOFT:
5979                 break;
5980         }
5981
5982         // allocate textures as needed
5983         if (r_bloomstate.screentexturewidth != screentexturewidth
5984          || r_bloomstate.screentextureheight != screentextureheight
5985          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5986          || r_bloomstate.bloomtextureheight != bloomtextureheight
5987          || r_bloomstate.texturetype != textype
5988          || r_bloomstate.viewfbo != r_viewfbo.integer)
5989         {
5990                 if (r_bloomstate.texture_bloom)
5991                         R_FreeTexture(r_bloomstate.texture_bloom);
5992                 r_bloomstate.texture_bloom = NULL;
5993                 if (r_bloomstate.texture_screen)
5994                         R_FreeTexture(r_bloomstate.texture_screen);
5995                 r_bloomstate.texture_screen = NULL;
5996                 if (r_bloomstate.fbo_framebuffer)
5997                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5998                 r_bloomstate.fbo_framebuffer = 0;
5999                 if (r_bloomstate.texture_framebuffercolor)
6000                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6001                 r_bloomstate.texture_framebuffercolor = NULL;
6002                 if (r_bloomstate.texture_framebufferdepth)
6003                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6004                 r_bloomstate.texture_framebufferdepth = NULL;
6005                 r_bloomstate.screentexturewidth = screentexturewidth;
6006                 r_bloomstate.screentextureheight = screentextureheight;
6007                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6008                         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);
6009                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6010                 {
6011                         // FIXME: choose depth bits based on a cvar
6012                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6013                         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);
6014                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6015                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6016                         // render depth into one texture and normalmap into the other
6017                         if (qglDrawBuffer)
6018                         {
6019                                 int status;
6020                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6021                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6022                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6023                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6024                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6025                         }
6026                 }
6027                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6028                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6029                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6030                         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);
6031                 r_bloomstate.viewfbo = r_viewfbo.integer;
6032                 r_bloomstate.texturetype = textype;
6033         }
6034
6035         // when doing a reduced render (HDR) we want to use a smaller area
6036         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6037         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6038         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6039         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6040         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6041
6042         // set up a texcoord array for the full resolution screen image
6043         // (we have to keep this around to copy back during final render)
6044         r_bloomstate.screentexcoord2f[0] = 0;
6045         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6046         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6047         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6048         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6049         r_bloomstate.screentexcoord2f[5] = 0;
6050         r_bloomstate.screentexcoord2f[6] = 0;
6051         r_bloomstate.screentexcoord2f[7] = 0;
6052
6053         // set up a texcoord array for the reduced resolution bloom image
6054         // (which will be additive blended over the screen image)
6055         r_bloomstate.bloomtexcoord2f[0] = 0;
6056         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6057         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6058         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6059         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6060         r_bloomstate.bloomtexcoord2f[5] = 0;
6061         r_bloomstate.bloomtexcoord2f[6] = 0;
6062         r_bloomstate.bloomtexcoord2f[7] = 0;
6063
6064         switch(vid.renderpath)
6065         {
6066         case RENDERPATH_GL11:
6067         case RENDERPATH_GL13:
6068         case RENDERPATH_GL20:
6069         case RENDERPATH_SOFT:
6070         case RENDERPATH_GLES1:
6071         case RENDERPATH_GLES2:
6072                 break;
6073         case RENDERPATH_D3D9:
6074         case RENDERPATH_D3D10:
6075         case RENDERPATH_D3D11:
6076                 {
6077                         int i;
6078                         for (i = 0;i < 4;i++)
6079                         {
6080                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6081                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6082                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6083                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6084                         }
6085                 }
6086                 break;
6087         }
6088
6089         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6090         {
6091                 r_bloomstate.enabled = true;
6092                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6093         }
6094
6095         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);
6096
6097         if (r_bloomstate.fbo_framebuffer)
6098                 r_refdef.view.clear = true;
6099 }
6100
6101 void R_Bloom_CopyBloomTexture(float colorscale)
6102 {
6103         r_refdef.stats.bloom++;
6104
6105         // scale down screen texture to the bloom texture size
6106         CHECKGLERROR
6107         R_Mesh_SetMainRenderTargets();
6108         R_SetViewport(&r_bloomstate.viewport);
6109         GL_BlendFunc(GL_ONE, GL_ZERO);
6110         GL_Color(colorscale, colorscale, colorscale, 1);
6111         // 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...
6112         switch(vid.renderpath)
6113         {
6114         case RENDERPATH_GL11:
6115         case RENDERPATH_GL13:
6116         case RENDERPATH_GL20:
6117         case RENDERPATH_GLES1:
6118         case RENDERPATH_GLES2:
6119         case RENDERPATH_SOFT:
6120                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6121                 break;
6122         case RENDERPATH_D3D9:
6123         case RENDERPATH_D3D10:
6124         case RENDERPATH_D3D11:
6125                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6126                 break;
6127         }
6128         // TODO: do boxfilter scale-down in shader?
6129         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6130         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6131         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6132
6133         // we now have a bloom image in the framebuffer
6134         // copy it into the bloom image texture for later processing
6135         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);
6136         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6137 }
6138
6139 void R_Bloom_CopyHDRTexture(void)
6140 {
6141         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);
6142         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6143 }
6144
6145 void R_Bloom_MakeTexture(void)
6146 {
6147         int x, range, dir;
6148         float xoffset, yoffset, r, brighten;
6149
6150         r_refdef.stats.bloom++;
6151
6152         R_ResetViewRendering2D();
6153
6154         // we have a bloom image in the framebuffer
6155         CHECKGLERROR
6156         R_SetViewport(&r_bloomstate.viewport);
6157
6158         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6159         {
6160                 x *= 2;
6161                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6162                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6163                 GL_Color(r,r,r,1);
6164                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6165                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6166                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6167                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6168
6169                 // copy the vertically blurred bloom view to a texture
6170                 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);
6171                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6172         }
6173
6174         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6175         brighten = r_bloom_brighten.value;
6176         if (r_bloomstate.hdr)
6177                 brighten *= r_hdr_range.value;
6178         brighten = sqrt(brighten);
6179         if(range >= 1)
6180                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6181         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6182
6183         for (dir = 0;dir < 2;dir++)
6184         {
6185                 // blend on at multiple vertical offsets to achieve a vertical blur
6186                 // TODO: do offset blends using GLSL
6187                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6188                 GL_BlendFunc(GL_ONE, GL_ZERO);
6189                 for (x = -range;x <= range;x++)
6190                 {
6191                         if (!dir){xoffset = 0;yoffset = x;}
6192                         else {xoffset = x;yoffset = 0;}
6193                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6194                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6195                         // compute a texcoord array with the specified x and y offset
6196                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6197                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6198                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6199                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6200                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6201                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6202                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6203                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6204                         // this r value looks like a 'dot' particle, fading sharply to
6205                         // black at the edges
6206                         // (probably not realistic but looks good enough)
6207                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6208                         //r = brighten/(range*2+1);
6209                         r = brighten / (range * 2 + 1);
6210                         if(range >= 1)
6211                                 r *= (1 - x*x/(float)(range*range));
6212                         GL_Color(r, r, r, 1);
6213                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6214                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6215                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6216                         GL_BlendFunc(GL_ONE, GL_ONE);
6217                 }
6218
6219                 // copy the vertically blurred bloom view to a texture
6220                 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);
6221                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6222         }
6223 }
6224
6225 void R_HDR_RenderBloomTexture(void)
6226 {
6227         int oldwidth, oldheight;
6228         float oldcolorscale;
6229         qboolean oldwaterstate;
6230
6231         oldwaterstate = r_waterstate.enabled;
6232         oldcolorscale = r_refdef.view.colorscale;
6233         oldwidth = r_refdef.view.width;
6234         oldheight = r_refdef.view.height;
6235         r_refdef.view.width = r_bloomstate.bloomwidth;
6236         r_refdef.view.height = r_bloomstate.bloomheight;
6237
6238         if(r_hdr.integer < 2)
6239                 r_waterstate.enabled = false;
6240
6241         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6242         // TODO: add exposure compensation features
6243         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6244
6245         r_refdef.view.showdebug = false;
6246         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6247
6248         R_ResetViewRendering3D();
6249
6250         R_ClearScreen(r_refdef.fogenabled);
6251         if (r_timereport_active)
6252                 R_TimeReport("HDRclear");
6253
6254         R_View_Update();
6255         if (r_timereport_active)
6256                 R_TimeReport("visibility");
6257
6258         // only do secondary renders with HDR if r_hdr is 2 or higher
6259         r_waterstate.numwaterplanes = 0;
6260         if (r_waterstate.enabled)
6261                 R_RenderWaterPlanes();
6262
6263         r_refdef.view.showdebug = true;
6264         R_RenderScene();
6265         r_waterstate.numwaterplanes = 0;
6266
6267         R_ResetViewRendering2D();
6268
6269         R_Bloom_CopyHDRTexture();
6270         R_Bloom_MakeTexture();
6271
6272         // restore the view settings
6273         r_waterstate.enabled = oldwaterstate;
6274         r_refdef.view.width = oldwidth;
6275         r_refdef.view.height = oldheight;
6276         r_refdef.view.colorscale = oldcolorscale;
6277
6278         R_ResetViewRendering3D();
6279
6280         R_ClearScreen(r_refdef.fogenabled);
6281         if (r_timereport_active)
6282                 R_TimeReport("viewclear");
6283 }
6284
6285 static void R_BlendView(void)
6286 {
6287         unsigned int permutation;
6288         float uservecs[4][4];
6289
6290         switch (vid.renderpath)
6291         {
6292         case RENDERPATH_GL20:
6293         case RENDERPATH_D3D9:
6294         case RENDERPATH_D3D10:
6295         case RENDERPATH_D3D11:
6296         case RENDERPATH_SOFT:
6297         case RENDERPATH_GLES2:
6298                 permutation =
6299                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6300                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6301                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6302                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6303                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6304
6305                 if (r_bloomstate.texture_screen)
6306                 {
6307                         // make sure the buffer is available
6308                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6309
6310                         R_ResetViewRendering2D();
6311                         R_Mesh_SetMainRenderTargets();
6312
6313                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6314                         {
6315                                 // declare variables
6316                                 float blur_factor, blur_mouseaccel, blur_velocity;
6317                                 static float blur_average; 
6318                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6319
6320                                 // set a goal for the factoring
6321                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6322                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6323                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6324                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6325                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6326                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6327
6328                                 // from the goal, pick an averaged value between goal and last value
6329                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6330                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6331                                 
6332                                 // enforce minimum amount of blur 
6333                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6334                                 
6335                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6336
6337                                 // calculate values into a standard alpha
6338                                 cl.motionbluralpha = 1 - exp(-
6339                                                 (
6340                                                  (r_motionblur.value * blur_factor / 80)
6341                                                  +
6342                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6343                                                 )
6344                                                 /
6345                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6346                                           );
6347                                 
6348                                 // randomization for the blur value to combat persistent ghosting
6349                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6350                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6351                                 
6352                                 // apply the blur
6353                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6354                                 {
6355                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6356                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6357                                         switch(vid.renderpath)
6358                                         {
6359                                         case RENDERPATH_GL11:
6360                                         case RENDERPATH_GL13:
6361                                         case RENDERPATH_GL20:
6362                                         case RENDERPATH_GLES1:
6363                                         case RENDERPATH_GLES2:
6364                                         case RENDERPATH_SOFT:
6365                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6366                                                 break;
6367                                         case RENDERPATH_D3D9:
6368                                         case RENDERPATH_D3D10:
6369                                         case RENDERPATH_D3D11:
6370                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6371                                                 break;
6372                                         }
6373                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6374                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6375                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6376                                 }
6377                                 
6378                                 // updates old view angles for next pass 
6379                                 VectorCopy(cl.viewangles, blur_oldangles);
6380                         }
6381
6382                         // copy view into the screen texture
6383                         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);
6384                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6385                 }
6386                 else if (!r_bloomstate.texture_bloom)
6387                 {
6388                         // we may still have to do view tint...
6389                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6390                         {
6391                                 // apply a color tint to the whole view
6392                                 R_ResetViewRendering2D();
6393                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6394                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6395                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6396                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6397                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6398                         }
6399                         break; // no screen processing, no bloom, skip it
6400                 }
6401
6402                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6403                 {
6404                         // render simple bloom effect
6405                         // copy the screen and shrink it and darken it for the bloom process
6406                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6407                         // make the bloom texture
6408                         R_Bloom_MakeTexture();
6409                 }
6410
6411 #if _MSC_VER >= 1400
6412 #define sscanf sscanf_s
6413 #endif
6414                 memset(uservecs, 0, sizeof(uservecs));
6415                 if (r_glsl_postprocess_uservec1_enable.integer)
6416                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6417                 if (r_glsl_postprocess_uservec2_enable.integer)
6418                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6419                 if (r_glsl_postprocess_uservec3_enable.integer)
6420                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6421                 if (r_glsl_postprocess_uservec4_enable.integer)
6422                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6423
6424                 R_ResetViewRendering2D();
6425                 GL_Color(1, 1, 1, 1);
6426                 GL_BlendFunc(GL_ONE, GL_ZERO);
6427
6428                 switch(vid.renderpath)
6429                 {
6430                 case RENDERPATH_GL20:
6431                 case RENDERPATH_GLES2:
6432                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6433                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6434                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6435                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6436                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6437                         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]);
6438                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6439                         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]);
6440                         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]);
6441                         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]);
6442                         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]);
6443                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6444                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6445                         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);
6446                         break;
6447                 case RENDERPATH_D3D9:
6448 #ifdef SUPPORTD3D
6449                         // 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...
6450                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6451                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6452                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6453                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6454                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6455                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6456                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6457                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6458                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6459                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6460                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6461                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6462                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6463                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6464 #endif
6465                         break;
6466                 case RENDERPATH_D3D10:
6467                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6468                         break;
6469                 case RENDERPATH_D3D11:
6470                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6471                         break;
6472                 case RENDERPATH_SOFT:
6473                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6474                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6475                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6476                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6477                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6478                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6479                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6480                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6481                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6482                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6483                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6484                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6485                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6486                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6487                         break;
6488                 default:
6489                         break;
6490                 }
6491                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6492                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6493                 break;
6494         case RENDERPATH_GL11:
6495         case RENDERPATH_GL13:
6496         case RENDERPATH_GLES1:
6497                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6498                 {
6499                         // apply a color tint to the whole view
6500                         R_ResetViewRendering2D();
6501                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6502                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6503                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6504                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6505                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6506                 }
6507                 break;
6508         }
6509 }
6510
6511 matrix4x4_t r_waterscrollmatrix;
6512
6513 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6514 {
6515         if (r_refdef.fog_density)
6516         {
6517                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6518                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6519                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6520
6521                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6522                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6523                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6524                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6525
6526                 {
6527                         vec3_t fogvec;
6528                         VectorCopy(r_refdef.fogcolor, fogvec);
6529                         //   color.rgb *= ContrastBoost * SceneBrightness;
6530                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6531                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6532                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6533                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6534                 }
6535         }
6536 }
6537
6538 void R_UpdateVariables(void)
6539 {
6540         R_Textures_Frame();
6541
6542         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6543
6544         r_refdef.farclip = r_farclip_base.value;
6545         if (r_refdef.scene.worldmodel)
6546                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6547         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6548
6549         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6550                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6551         r_refdef.polygonfactor = 0;
6552         r_refdef.polygonoffset = 0;
6553         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6554         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6555
6556         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6557         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6558         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6559         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6560         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6561         if (FAKELIGHT_ENABLED)
6562         {
6563                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6564         }
6565         if (r_showsurfaces.integer)
6566         {
6567                 r_refdef.scene.rtworld = false;
6568                 r_refdef.scene.rtworldshadows = false;
6569                 r_refdef.scene.rtdlight = false;
6570                 r_refdef.scene.rtdlightshadows = false;
6571                 r_refdef.lightmapintensity = 0;
6572         }
6573
6574         if (gamemode == GAME_NEHAHRA)
6575         {
6576                 if (gl_fogenable.integer)
6577                 {
6578                         r_refdef.oldgl_fogenable = true;
6579                         r_refdef.fog_density = gl_fogdensity.value;
6580                         r_refdef.fog_red = gl_fogred.value;
6581                         r_refdef.fog_green = gl_foggreen.value;
6582                         r_refdef.fog_blue = gl_fogblue.value;
6583                         r_refdef.fog_alpha = 1;
6584                         r_refdef.fog_start = 0;
6585                         r_refdef.fog_end = gl_skyclip.value;
6586                         r_refdef.fog_height = 1<<30;
6587                         r_refdef.fog_fadedepth = 128;
6588                 }
6589                 else if (r_refdef.oldgl_fogenable)
6590                 {
6591                         r_refdef.oldgl_fogenable = false;
6592                         r_refdef.fog_density = 0;
6593                         r_refdef.fog_red = 0;
6594                         r_refdef.fog_green = 0;
6595                         r_refdef.fog_blue = 0;
6596                         r_refdef.fog_alpha = 0;
6597                         r_refdef.fog_start = 0;
6598                         r_refdef.fog_end = 0;
6599                         r_refdef.fog_height = 1<<30;
6600                         r_refdef.fog_fadedepth = 128;
6601                 }
6602         }
6603
6604         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6605         r_refdef.fog_start = max(0, r_refdef.fog_start);
6606         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6607
6608         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6609
6610         if (r_refdef.fog_density && r_drawfog.integer)
6611         {
6612                 r_refdef.fogenabled = true;
6613                 // this is the point where the fog reaches 0.9986 alpha, which we
6614                 // consider a good enough cutoff point for the texture
6615                 // (0.9986 * 256 == 255.6)
6616                 if (r_fog_exp2.integer)
6617                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6618                 else
6619                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6620                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6621                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6622                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6623                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6624                         R_BuildFogHeightTexture();
6625                 // fog color was already set
6626                 // update the fog texture
6627                 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)
6628                         R_BuildFogTexture();
6629                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6630                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6631         }
6632         else
6633                 r_refdef.fogenabled = false;
6634
6635         switch(vid.renderpath)
6636         {
6637         case RENDERPATH_GL20:
6638         case RENDERPATH_D3D9:
6639         case RENDERPATH_D3D10:
6640         case RENDERPATH_D3D11:
6641         case RENDERPATH_SOFT:
6642         case RENDERPATH_GLES2:
6643                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6644                 {
6645                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6646                         {
6647                                 // build GLSL gamma texture
6648 #define RAMPWIDTH 256
6649                                 unsigned short ramp[RAMPWIDTH * 3];
6650                                 unsigned char rampbgr[RAMPWIDTH][4];
6651                                 int i;
6652
6653                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6654
6655                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6656                                 for(i = 0; i < RAMPWIDTH; ++i)
6657                                 {
6658                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6659                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6660                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6661                                         rampbgr[i][3] = 0;
6662                                 }
6663                                 if (r_texture_gammaramps)
6664                                 {
6665                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6666                                 }
6667                                 else
6668                                 {
6669                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6670                                 }
6671                         }
6672                 }
6673                 else
6674                 {
6675                         // remove GLSL gamma texture
6676                 }
6677                 break;
6678         case RENDERPATH_GL11:
6679         case RENDERPATH_GL13:
6680         case RENDERPATH_GLES1:
6681                 break;
6682         }
6683 }
6684
6685 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6686 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6687 /*
6688 ================
6689 R_SelectScene
6690 ================
6691 */
6692 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6693         if( scenetype != r_currentscenetype ) {
6694                 // store the old scenetype
6695                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6696                 r_currentscenetype = scenetype;
6697                 // move in the new scene
6698                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6699         }
6700 }
6701
6702 /*
6703 ================
6704 R_GetScenePointer
6705 ================
6706 */
6707 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6708 {
6709         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6710         if( scenetype == r_currentscenetype ) {
6711                 return &r_refdef.scene;
6712         } else {
6713                 return &r_scenes_store[ scenetype ];
6714         }
6715 }
6716
6717 /*
6718 ================
6719 R_RenderView
6720 ================
6721 */
6722 int dpsoftrast_test;
6723 extern void R_Shadow_UpdateBounceGridTexture(void);
6724 extern cvar_t r_shadow_bouncegrid;
6725 void R_RenderView(void)
6726 {
6727         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6728
6729         dpsoftrast_test = r_test.integer;
6730
6731         if (r_timereport_active)
6732                 R_TimeReport("start");
6733         r_textureframe++; // used only by R_GetCurrentTexture
6734         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6735
6736         if(R_CompileShader_CheckStaticParms())
6737                 R_GLSL_Restart_f();
6738
6739         if (!r_drawentities.integer)
6740                 r_refdef.scene.numentities = 0;
6741
6742         R_AnimCache_ClearCache();
6743         R_FrameData_NewFrame();
6744
6745         /* adjust for stereo display */
6746         if(R_Stereo_Active())
6747         {
6748                 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);
6749                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6750         }
6751
6752         if (r_refdef.view.isoverlay)
6753         {
6754                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6755                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6756                 R_TimeReport("depthclear");
6757
6758                 r_refdef.view.showdebug = false;
6759
6760                 r_waterstate.enabled = false;
6761                 r_waterstate.numwaterplanes = 0;
6762
6763                 R_RenderScene();
6764
6765                 r_refdef.view.matrix = originalmatrix;
6766
6767                 CHECKGLERROR
6768                 return;
6769         }
6770
6771         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6772         {
6773                 r_refdef.view.matrix = originalmatrix;
6774                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6775         }
6776
6777         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6778
6779         R_RenderView_UpdateViewVectors();
6780
6781         R_Shadow_UpdateWorldLightSelection();
6782
6783         R_Bloom_StartFrame();
6784         R_Water_StartFrame();
6785
6786         CHECKGLERROR
6787         if (r_timereport_active)
6788                 R_TimeReport("viewsetup");
6789
6790         R_ResetViewRendering3D();
6791
6792         if (r_refdef.view.clear || r_refdef.fogenabled)
6793         {
6794                 R_ClearScreen(r_refdef.fogenabled);
6795                 if (r_timereport_active)
6796                         R_TimeReport("viewclear");
6797         }
6798         r_refdef.view.clear = true;
6799
6800         // this produces a bloom texture to be used in R_BlendView() later
6801         if (r_bloomstate.hdr)
6802         {
6803                 R_HDR_RenderBloomTexture();
6804                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6805                 r_textureframe++; // used only by R_GetCurrentTexture
6806         }
6807
6808         r_refdef.view.showdebug = true;
6809
6810         R_View_Update();
6811         if (r_timereport_active)
6812                 R_TimeReport("visibility");
6813
6814         R_Shadow_UpdateBounceGridTexture();
6815         if (r_timereport_active && r_shadow_bouncegrid.integer)
6816                 R_TimeReport("bouncegrid");
6817
6818         r_waterstate.numwaterplanes = 0;
6819         if (r_waterstate.enabled)
6820                 R_RenderWaterPlanes();
6821
6822         R_RenderScene();
6823         r_waterstate.numwaterplanes = 0;
6824
6825         R_BlendView();
6826         if (r_timereport_active)
6827                 R_TimeReport("blendview");
6828
6829         GL_Scissor(0, 0, vid.width, vid.height);
6830         GL_ScissorTest(false);
6831
6832         r_refdef.view.matrix = originalmatrix;
6833
6834         CHECKGLERROR
6835 }
6836
6837 void R_RenderWaterPlanes(void)
6838 {
6839         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6840         {
6841                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6842                 if (r_timereport_active)
6843                         R_TimeReport("waterworld");
6844         }
6845
6846         // don't let sound skip if going slow
6847         if (r_refdef.scene.extraupdate)
6848                 S_ExtraUpdate ();
6849
6850         R_DrawModelsAddWaterPlanes();
6851         if (r_timereport_active)
6852                 R_TimeReport("watermodels");
6853
6854         if (r_waterstate.numwaterplanes)
6855         {
6856                 R_Water_ProcessPlanes();
6857                 if (r_timereport_active)
6858                         R_TimeReport("waterscenes");
6859         }
6860 }
6861
6862 extern void R_DrawLightningBeams (void);
6863 extern void VM_CL_AddPolygonsToMeshQueue (void);
6864 extern void R_DrawPortals (void);
6865 extern cvar_t cl_locs_show;
6866 static void R_DrawLocs(void);
6867 static void R_DrawEntityBBoxes(void);
6868 static void R_DrawModelDecals(void);
6869 extern void R_DrawModelShadows(void);
6870 extern void R_DrawModelShadowMaps(void);
6871 extern cvar_t cl_decals_newsystem;
6872 extern qboolean r_shadow_usingdeferredprepass;
6873 void R_RenderScene(void)
6874 {
6875         qboolean shadowmapping = false;
6876
6877         if (r_timereport_active)
6878                 R_TimeReport("beginscene");
6879
6880         r_refdef.stats.renders++;
6881
6882         R_UpdateFogColor();
6883
6884         // don't let sound skip if going slow
6885         if (r_refdef.scene.extraupdate)
6886                 S_ExtraUpdate ();
6887
6888         R_MeshQueue_BeginScene();
6889
6890         R_SkyStartFrame();
6891
6892         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);
6893
6894         if (r_timereport_active)
6895                 R_TimeReport("skystartframe");
6896
6897         if (cl.csqc_vidvars.drawworld)
6898         {
6899                 // don't let sound skip if going slow
6900                 if (r_refdef.scene.extraupdate)
6901                         S_ExtraUpdate ();
6902
6903                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6904                 {
6905                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6906                         if (r_timereport_active)
6907                                 R_TimeReport("worldsky");
6908                 }
6909
6910                 if (R_DrawBrushModelsSky() && r_timereport_active)
6911                         R_TimeReport("bmodelsky");
6912
6913                 if (skyrendermasked && skyrenderlater)
6914                 {
6915                         // we have to force off the water clipping plane while rendering sky
6916                         R_SetupView(false);
6917                         R_Sky();
6918                         R_SetupView(true);
6919                         if (r_timereport_active)
6920                                 R_TimeReport("sky");
6921                 }
6922         }
6923
6924         R_AnimCache_CacheVisibleEntities();
6925         if (r_timereport_active)
6926                 R_TimeReport("animation");
6927
6928         R_Shadow_PrepareLights();
6929         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6930                 R_Shadow_PrepareModelShadows();
6931         if (r_timereport_active)
6932                 R_TimeReport("preparelights");
6933
6934         if (R_Shadow_ShadowMappingEnabled())
6935                 shadowmapping = true;
6936
6937         if (r_shadow_usingdeferredprepass)
6938                 R_Shadow_DrawPrepass();
6939
6940         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6941         {
6942                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6943                 if (r_timereport_active)
6944                         R_TimeReport("worlddepth");
6945         }
6946         if (r_depthfirst.integer >= 2)
6947         {
6948                 R_DrawModelsDepth();
6949                 if (r_timereport_active)
6950                         R_TimeReport("modeldepth");
6951         }
6952
6953         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6954         {
6955                 R_DrawModelShadowMaps();
6956                 R_ResetViewRendering3D();
6957                 // don't let sound skip if going slow
6958                 if (r_refdef.scene.extraupdate)
6959                         S_ExtraUpdate ();
6960         }
6961
6962         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6963         {
6964                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6965                 if (r_timereport_active)
6966                         R_TimeReport("world");
6967         }
6968
6969         // don't let sound skip if going slow
6970         if (r_refdef.scene.extraupdate)
6971                 S_ExtraUpdate ();
6972
6973         R_DrawModels();
6974         if (r_timereport_active)
6975                 R_TimeReport("models");
6976
6977         // don't let sound skip if going slow
6978         if (r_refdef.scene.extraupdate)
6979                 S_ExtraUpdate ();
6980
6981         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6982         {
6983                 R_DrawModelShadows();
6984                 R_ResetViewRendering3D();
6985                 // don't let sound skip if going slow
6986                 if (r_refdef.scene.extraupdate)
6987                         S_ExtraUpdate ();
6988         }
6989
6990         if (!r_shadow_usingdeferredprepass)
6991         {
6992                 R_Shadow_DrawLights();
6993                 if (r_timereport_active)
6994                         R_TimeReport("rtlights");
6995         }
6996
6997         // don't let sound skip if going slow
6998         if (r_refdef.scene.extraupdate)
6999                 S_ExtraUpdate ();
7000
7001         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7002         {
7003                 R_DrawModelShadows();
7004                 R_ResetViewRendering3D();
7005                 // don't let sound skip if going slow
7006                 if (r_refdef.scene.extraupdate)
7007                         S_ExtraUpdate ();
7008         }
7009
7010         if (cl.csqc_vidvars.drawworld)
7011         {
7012                 if (cl_decals_newsystem.integer)
7013                 {
7014                         R_DrawModelDecals();
7015                         if (r_timereport_active)
7016                                 R_TimeReport("modeldecals");
7017                 }
7018                 else
7019                 {
7020                         R_DrawDecals();
7021                         if (r_timereport_active)
7022                                 R_TimeReport("decals");
7023                 }
7024
7025                 R_DrawParticles();
7026                 if (r_timereport_active)
7027                         R_TimeReport("particles");
7028
7029                 R_DrawExplosions();
7030                 if (r_timereport_active)
7031                         R_TimeReport("explosions");
7032
7033                 R_DrawLightningBeams();
7034                 if (r_timereport_active)
7035                         R_TimeReport("lightning");
7036         }
7037
7038         VM_CL_AddPolygonsToMeshQueue();
7039
7040         if (r_refdef.view.showdebug)
7041         {
7042                 if (cl_locs_show.integer)
7043                 {
7044                         R_DrawLocs();
7045                         if (r_timereport_active)
7046                                 R_TimeReport("showlocs");
7047                 }
7048
7049                 if (r_drawportals.integer)
7050                 {
7051                         R_DrawPortals();
7052                         if (r_timereport_active)
7053                                 R_TimeReport("portals");
7054                 }
7055
7056                 if (r_showbboxes.value > 0)
7057                 {
7058                         R_DrawEntityBBoxes();
7059                         if (r_timereport_active)
7060                                 R_TimeReport("bboxes");
7061                 }
7062         }
7063
7064         if (r_transparent.integer)
7065         {
7066                 R_MeshQueue_RenderTransparent();
7067                 if (r_timereport_active)
7068                         R_TimeReport("drawtrans");
7069         }
7070
7071         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))
7072         {
7073                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7074                 if (r_timereport_active)
7075                         R_TimeReport("worlddebug");
7076                 R_DrawModelsDebug();
7077                 if (r_timereport_active)
7078                         R_TimeReport("modeldebug");
7079         }
7080
7081         if (cl.csqc_vidvars.drawworld)
7082         {
7083                 R_Shadow_DrawCoronas();
7084                 if (r_timereport_active)
7085                         R_TimeReport("coronas");
7086         }
7087
7088 #if 0
7089         {
7090                 GL_DepthTest(false);
7091                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7092                 GL_Color(1, 1, 1, 1);
7093                 qglBegin(GL_POLYGON);
7094                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7095                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7096                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7097                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7098                 qglEnd();
7099                 qglBegin(GL_POLYGON);
7100                 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]);
7101                 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]);
7102                 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]);
7103                 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]);
7104                 qglEnd();
7105                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7106         }
7107 #endif
7108
7109         // don't let sound skip if going slow
7110         if (r_refdef.scene.extraupdate)
7111                 S_ExtraUpdate ();
7112
7113         R_ResetViewRendering2D();
7114 }
7115
7116 static const unsigned short bboxelements[36] =
7117 {
7118         5, 1, 3, 5, 3, 7,
7119         6, 2, 0, 6, 0, 4,
7120         7, 3, 2, 7, 2, 6,
7121         4, 0, 1, 4, 1, 5,
7122         4, 5, 7, 4, 7, 6,
7123         1, 0, 2, 1, 2, 3,
7124 };
7125
7126 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7127 {
7128         int i;
7129         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7130
7131         RSurf_ActiveWorldEntity();
7132
7133         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7134         GL_DepthMask(false);
7135         GL_DepthRange(0, 1);
7136         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7137 //      R_Mesh_ResetTextureState();
7138
7139         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7140         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7141         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7142         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7143         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7144         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7145         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7146         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7147         R_FillColors(color4f, 8, cr, cg, cb, ca);
7148         if (r_refdef.fogenabled)
7149         {
7150                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7151                 {
7152                         f1 = RSurf_FogVertex(v);
7153                         f2 = 1 - f1;
7154                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7155                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7156                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7157                 }
7158         }
7159         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7160         R_Mesh_ResetTextureState();
7161         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7162         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7163 }
7164
7165 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7166 {
7167         int i;
7168         float color[4];
7169         prvm_edict_t *edict;
7170         prvm_prog_t *prog_save = prog;
7171
7172         // this function draws bounding boxes of server entities
7173         if (!sv.active)
7174                 return;
7175
7176         GL_CullFace(GL_NONE);
7177         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7178
7179         prog = 0;
7180         SV_VM_Begin();
7181         for (i = 0;i < numsurfaces;i++)
7182         {
7183                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7184                 switch ((int)PRVM_serveredictfloat(edict, solid))
7185                 {
7186                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7187                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7188                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7189                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7190                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7191                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7192                 }
7193                 color[3] *= r_showbboxes.value;
7194                 color[3] = bound(0, color[3], 1);
7195                 GL_DepthTest(!r_showdisabledepthtest.integer);
7196                 GL_CullFace(r_refdef.view.cullface_front);
7197                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7198         }
7199         SV_VM_End();
7200         prog = prog_save;
7201 }
7202
7203 static void R_DrawEntityBBoxes(void)
7204 {
7205         int i;
7206         prvm_edict_t *edict;
7207         vec3_t center;
7208         prvm_prog_t *prog_save = prog;
7209
7210         // this function draws bounding boxes of server entities
7211         if (!sv.active)
7212                 return;
7213
7214         prog = 0;
7215         SV_VM_Begin();
7216         for (i = 0;i < prog->num_edicts;i++)
7217         {
7218                 edict = PRVM_EDICT_NUM(i);
7219                 if (edict->priv.server->free)
7220                         continue;
7221                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7222                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7223                         continue;
7224                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7225                         continue;
7226                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7227                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7228         }
7229         SV_VM_End();
7230         prog = prog_save;
7231 }
7232
7233 static const int nomodelelement3i[24] =
7234 {
7235         5, 2, 0,
7236         5, 1, 2,
7237         5, 0, 3,
7238         5, 3, 1,
7239         0, 2, 4,
7240         2, 1, 4,
7241         3, 0, 4,
7242         1, 3, 4
7243 };
7244
7245 static const unsigned short nomodelelement3s[24] =
7246 {
7247         5, 2, 0,
7248         5, 1, 2,
7249         5, 0, 3,
7250         5, 3, 1,
7251         0, 2, 4,
7252         2, 1, 4,
7253         3, 0, 4,
7254         1, 3, 4
7255 };
7256
7257 static const float nomodelvertex3f[6*3] =
7258 {
7259         -16,   0,   0,
7260          16,   0,   0,
7261           0, -16,   0,
7262           0,  16,   0,
7263           0,   0, -16,
7264           0,   0,  16
7265 };
7266
7267 static const float nomodelcolor4f[6*4] =
7268 {
7269         0.0f, 0.0f, 0.5f, 1.0f,
7270         0.0f, 0.0f, 0.5f, 1.0f,
7271         0.0f, 0.5f, 0.0f, 1.0f,
7272         0.0f, 0.5f, 0.0f, 1.0f,
7273         0.5f, 0.0f, 0.0f, 1.0f,
7274         0.5f, 0.0f, 0.0f, 1.0f
7275 };
7276
7277 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7278 {
7279         int i;
7280         float f1, f2, *c;
7281         float color4f[6*4];
7282
7283         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);
7284
7285         // this is only called once per entity so numsurfaces is always 1, and
7286         // surfacelist is always {0}, so this code does not handle batches
7287
7288         if (rsurface.ent_flags & RENDER_ADDITIVE)
7289         {
7290                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7291                 GL_DepthMask(false);
7292         }
7293         else if (rsurface.colormod[3] < 1)
7294         {
7295                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7296                 GL_DepthMask(false);
7297         }
7298         else
7299         {
7300                 GL_BlendFunc(GL_ONE, GL_ZERO);
7301                 GL_DepthMask(true);
7302         }
7303         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7304         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7305         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7306         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7307         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7308         for (i = 0, c = color4f;i < 6;i++, c += 4)
7309         {
7310                 c[0] *= rsurface.colormod[0];
7311                 c[1] *= rsurface.colormod[1];
7312                 c[2] *= rsurface.colormod[2];
7313                 c[3] *= rsurface.colormod[3];
7314         }
7315         if (r_refdef.fogenabled)
7316         {
7317                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7318                 {
7319                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7320                         f2 = 1 - f1;
7321                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7322                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7323                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7324                 }
7325         }
7326 //      R_Mesh_ResetTextureState();
7327         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7328         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7329         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7330 }
7331
7332 void R_DrawNoModel(entity_render_t *ent)
7333 {
7334         vec3_t org;
7335         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7336         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7337                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7338         else
7339                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7340 }
7341
7342 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7343 {
7344         vec3_t right1, right2, diff, normal;
7345
7346         VectorSubtract (org2, org1, normal);
7347
7348         // calculate 'right' vector for start
7349         VectorSubtract (r_refdef.view.origin, org1, diff);
7350         CrossProduct (normal, diff, right1);
7351         VectorNormalize (right1);
7352
7353         // calculate 'right' vector for end
7354         VectorSubtract (r_refdef.view.origin, org2, diff);
7355         CrossProduct (normal, diff, right2);
7356         VectorNormalize (right2);
7357
7358         vert[ 0] = org1[0] + width * right1[0];
7359         vert[ 1] = org1[1] + width * right1[1];
7360         vert[ 2] = org1[2] + width * right1[2];
7361         vert[ 3] = org1[0] - width * right1[0];
7362         vert[ 4] = org1[1] - width * right1[1];
7363         vert[ 5] = org1[2] - width * right1[2];
7364         vert[ 6] = org2[0] - width * right2[0];
7365         vert[ 7] = org2[1] - width * right2[1];
7366         vert[ 8] = org2[2] - width * right2[2];
7367         vert[ 9] = org2[0] + width * right2[0];
7368         vert[10] = org2[1] + width * right2[1];
7369         vert[11] = org2[2] + width * right2[2];
7370 }
7371
7372 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)
7373 {
7374         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7375         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7376         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7377         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7378         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7379         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7380         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7381         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7382         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7383         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7384         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7385         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7386 }
7387
7388 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7389 {
7390         int i;
7391         float *vertex3f;
7392         float v[3];
7393         VectorSet(v, x, y, z);
7394         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7395                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7396                         break;
7397         if (i == mesh->numvertices)
7398         {
7399                 if (mesh->numvertices < mesh->maxvertices)
7400                 {
7401                         VectorCopy(v, vertex3f);
7402                         mesh->numvertices++;
7403                 }
7404                 return mesh->numvertices;
7405         }
7406         else
7407                 return i;
7408 }
7409
7410 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7411 {
7412         int i;
7413         int *e, element[3];
7414         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7415         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7416         e = mesh->element3i + mesh->numtriangles * 3;
7417         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7418         {
7419                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7420                 if (mesh->numtriangles < mesh->maxtriangles)
7421                 {
7422                         *e++ = element[0];
7423                         *e++ = element[1];
7424                         *e++ = element[2];
7425                         mesh->numtriangles++;
7426                 }
7427                 element[1] = element[2];
7428         }
7429 }
7430
7431 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7432 {
7433         int i;
7434         int *e, element[3];
7435         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7436         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7437         e = mesh->element3i + mesh->numtriangles * 3;
7438         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7439         {
7440                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7441                 if (mesh->numtriangles < mesh->maxtriangles)
7442                 {
7443                         *e++ = element[0];
7444                         *e++ = element[1];
7445                         *e++ = element[2];
7446                         mesh->numtriangles++;
7447                 }
7448                 element[1] = element[2];
7449         }
7450 }
7451
7452 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7453 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7454 {
7455         int planenum, planenum2;
7456         int w;
7457         int tempnumpoints;
7458         mplane_t *plane, *plane2;
7459         double maxdist;
7460         double temppoints[2][256*3];
7461         // figure out how large a bounding box we need to properly compute this brush
7462         maxdist = 0;
7463         for (w = 0;w < numplanes;w++)
7464                 maxdist = max(maxdist, fabs(planes[w].dist));
7465         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7466         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7467         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7468         {
7469                 w = 0;
7470                 tempnumpoints = 4;
7471                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7472                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7473                 {
7474                         if (planenum2 == planenum)
7475                                 continue;
7476                         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);
7477                         w = !w;
7478                 }
7479                 if (tempnumpoints < 3)
7480                         continue;
7481                 // generate elements forming a triangle fan for this polygon
7482                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7483         }
7484 }
7485
7486 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)
7487 {
7488         texturelayer_t *layer;
7489         layer = t->currentlayers + t->currentnumlayers++;
7490         layer->type = type;
7491         layer->depthmask = depthmask;
7492         layer->blendfunc1 = blendfunc1;
7493         layer->blendfunc2 = blendfunc2;
7494         layer->texture = texture;
7495         layer->texmatrix = *matrix;
7496         layer->color[0] = r;
7497         layer->color[1] = g;
7498         layer->color[2] = b;
7499         layer->color[3] = a;
7500 }
7501
7502 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7503 {
7504         if(parms[0] == 0 && parms[1] == 0)
7505                 return false;
7506         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7507                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7508                         return false;
7509         return true;
7510 }
7511
7512 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7513 {
7514         double index, f;
7515         index = parms[2] + rsurface.shadertime * parms[3];
7516         index -= floor(index);
7517         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7518         {
7519         default:
7520         case Q3WAVEFUNC_NONE:
7521         case Q3WAVEFUNC_NOISE:
7522         case Q3WAVEFUNC_COUNT:
7523                 f = 0;
7524                 break;
7525         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7526         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7527         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7528         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7529         case Q3WAVEFUNC_TRIANGLE:
7530                 index *= 4;
7531                 f = index - floor(index);
7532                 if (index < 1)
7533                 {
7534                         // f = f;
7535                 }
7536                 else if (index < 2)
7537                         f = 1 - f;
7538                 else if (index < 3)
7539                         f = -f;
7540                 else
7541                         f = -(1 - f);
7542                 break;
7543         }
7544         f = parms[0] + parms[1] * f;
7545         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7546                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7547         return (float) f;
7548 }
7549
7550 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7551 {
7552         int w, h, idx;
7553         double f;
7554         double offsetd[2];
7555         float tcmat[12];
7556         matrix4x4_t matrix, temp;
7557         switch(tcmod->tcmod)
7558         {
7559                 case Q3TCMOD_COUNT:
7560                 case Q3TCMOD_NONE:
7561                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7562                                 matrix = r_waterscrollmatrix;
7563                         else
7564                                 matrix = identitymatrix;
7565                         break;
7566                 case Q3TCMOD_ENTITYTRANSLATE:
7567                         // this is used in Q3 to allow the gamecode to control texcoord
7568                         // scrolling on the entity, which is not supported in darkplaces yet.
7569                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7570                         break;
7571                 case Q3TCMOD_ROTATE:
7572                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7573                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7574                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7575                         break;
7576                 case Q3TCMOD_SCALE:
7577                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7578                         break;
7579                 case Q3TCMOD_SCROLL:
7580                         // extra care is needed because of precision breakdown with large values of time
7581                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7582                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7583                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7584                         break;
7585                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7586                         w = (int) tcmod->parms[0];
7587                         h = (int) tcmod->parms[1];
7588                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7589                         f = f - floor(f);
7590                         idx = (int) floor(f * w * h);
7591                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7592                         break;
7593                 case Q3TCMOD_STRETCH:
7594                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7595                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7596                         break;
7597                 case Q3TCMOD_TRANSFORM:
7598                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7599                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7600                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7601                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7602                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7603                         break;
7604                 case Q3TCMOD_TURBULENT:
7605                         // this is handled in the RSurf_PrepareVertices function
7606                         matrix = identitymatrix;
7607                         break;
7608         }
7609         temp = *texmatrix;
7610         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7611 }
7612
7613 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7614 {
7615         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7616         char name[MAX_QPATH];
7617         skinframe_t *skinframe;
7618         unsigned char pixels[296*194];
7619         strlcpy(cache->name, skinname, sizeof(cache->name));
7620         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7621         if (developer_loading.integer)
7622                 Con_Printf("loading %s\n", name);
7623         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7624         if (!skinframe || !skinframe->base)
7625         {
7626                 unsigned char *f;
7627                 fs_offset_t filesize;
7628                 skinframe = NULL;
7629                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7630                 if (f)
7631                 {
7632                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7633                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7634                         Mem_Free(f);
7635                 }
7636         }
7637         cache->skinframe = skinframe;
7638 }
7639
7640 texture_t *R_GetCurrentTexture(texture_t *t)
7641 {
7642         int i;
7643         const entity_render_t *ent = rsurface.entity;
7644         dp_model_t *model = ent->model;
7645         q3shaderinfo_layer_tcmod_t *tcmod;
7646
7647         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7648                 return t->currentframe;
7649         t->update_lastrenderframe = r_textureframe;
7650         t->update_lastrenderentity = (void *)ent;
7651
7652         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7653                 t->camera_entity = ent->entitynumber;
7654         else
7655                 t->camera_entity = 0;
7656
7657         // switch to an alternate material if this is a q1bsp animated material
7658         {
7659                 texture_t *texture = t;
7660                 int s = rsurface.ent_skinnum;
7661                 if ((unsigned int)s >= (unsigned int)model->numskins)
7662                         s = 0;
7663                 if (model->skinscenes)
7664                 {
7665                         if (model->skinscenes[s].framecount > 1)
7666                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7667                         else
7668                                 s = model->skinscenes[s].firstframe;
7669                 }
7670                 if (s > 0)
7671                         t = t + s * model->num_surfaces;
7672                 if (t->animated)
7673                 {
7674                         // use an alternate animation if the entity's frame is not 0,
7675                         // and only if the texture has an alternate animation
7676                         if (rsurface.ent_alttextures && t->anim_total[1])
7677                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7678                         else
7679                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7680                 }
7681                 texture->currentframe = t;
7682         }
7683
7684         // update currentskinframe to be a qw skin or animation frame
7685         if (rsurface.ent_qwskin >= 0)
7686         {
7687                 i = rsurface.ent_qwskin;
7688                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7689                 {
7690                         r_qwskincache_size = cl.maxclients;
7691                         if (r_qwskincache)
7692                                 Mem_Free(r_qwskincache);
7693                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7694                 }
7695                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7696                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7697                 t->currentskinframe = r_qwskincache[i].skinframe;
7698                 if (t->currentskinframe == NULL)
7699                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7700         }
7701         else if (t->numskinframes >= 2)
7702                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7703         if (t->backgroundnumskinframes >= 2)
7704                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7705
7706         t->currentmaterialflags = t->basematerialflags;
7707         t->currentalpha = rsurface.colormod[3];
7708         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7709                 t->currentalpha *= r_wateralpha.value;
7710         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7711                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7712         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7713                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7714         if (!(rsurface.ent_flags & RENDER_LIGHT))
7715                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7716         else if (FAKELIGHT_ENABLED)
7717         {
7718                 // no modellight if using fakelight for the map
7719         }
7720         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7721         {
7722                 // pick a model lighting mode
7723                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7724                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7725                 else
7726                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7727         }
7728         if (rsurface.ent_flags & RENDER_ADDITIVE)
7729                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7730         else if (t->currentalpha < 1)
7731                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7732         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7733                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7734         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7735                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7736         if (t->backgroundnumskinframes)
7737                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7738         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7739         {
7740                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7741                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7742         }
7743         else
7744                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7745         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7746         {
7747                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7748                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7749         }
7750         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7751                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7752
7753         // there is no tcmod
7754         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7755         {
7756                 t->currenttexmatrix = r_waterscrollmatrix;
7757                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7758         }
7759         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7760         {
7761                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7762                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7763         }
7764
7765         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7766                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7767         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7768                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7769
7770         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7771         if (t->currentskinframe->qpixels)
7772                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7773         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7774         if (!t->basetexture)
7775                 t->basetexture = r_texture_notexture;
7776         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7777         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7778         t->nmaptexture = t->currentskinframe->nmap;
7779         if (!t->nmaptexture)
7780                 t->nmaptexture = r_texture_blanknormalmap;
7781         t->glosstexture = r_texture_black;
7782         t->glowtexture = t->currentskinframe->glow;
7783         t->fogtexture = t->currentskinframe->fog;
7784         t->reflectmasktexture = t->currentskinframe->reflect;
7785         if (t->backgroundnumskinframes)
7786         {
7787                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7788                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7789                 t->backgroundglosstexture = r_texture_black;
7790                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7791                 if (!t->backgroundnmaptexture)
7792                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7793         }
7794         else
7795         {
7796                 t->backgroundbasetexture = r_texture_white;
7797                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7798                 t->backgroundglosstexture = r_texture_black;
7799                 t->backgroundglowtexture = NULL;
7800         }
7801         t->specularpower = r_shadow_glossexponent.value;
7802         // TODO: store reference values for these in the texture?
7803         t->specularscale = 0;
7804         if (r_shadow_gloss.integer > 0)
7805         {
7806                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7807                 {
7808                         if (r_shadow_glossintensity.value > 0)
7809                         {
7810                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7811                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7812                                 t->specularscale = r_shadow_glossintensity.value;
7813                         }
7814                 }
7815                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7816                 {
7817                         t->glosstexture = r_texture_white;
7818                         t->backgroundglosstexture = r_texture_white;
7819                         t->specularscale = r_shadow_gloss2intensity.value;
7820                         t->specularpower = r_shadow_gloss2exponent.value;
7821                 }
7822         }
7823         t->specularscale *= t->specularscalemod;
7824         t->specularpower *= t->specularpowermod;
7825
7826         // lightmaps mode looks bad with dlights using actual texturing, so turn
7827         // off the colormap and glossmap, but leave the normalmap on as it still
7828         // accurately represents the shading involved
7829         if (gl_lightmaps.integer)
7830         {
7831                 t->basetexture = r_texture_grey128;
7832                 t->pantstexture = r_texture_black;
7833                 t->shirttexture = r_texture_black;
7834                 t->nmaptexture = r_texture_blanknormalmap;
7835                 t->glosstexture = r_texture_black;
7836                 t->glowtexture = NULL;
7837                 t->fogtexture = NULL;
7838                 t->reflectmasktexture = NULL;
7839                 t->backgroundbasetexture = NULL;
7840                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7841                 t->backgroundglosstexture = r_texture_black;
7842                 t->backgroundglowtexture = NULL;
7843                 t->specularscale = 0;
7844                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7845         }
7846
7847         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7848         VectorClear(t->dlightcolor);
7849         t->currentnumlayers = 0;
7850         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7851         {
7852                 int blendfunc1, blendfunc2;
7853                 qboolean depthmask;
7854                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7855                 {
7856                         blendfunc1 = GL_SRC_ALPHA;
7857                         blendfunc2 = GL_ONE;
7858                 }
7859                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7860                 {
7861                         blendfunc1 = GL_SRC_ALPHA;
7862                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7863                 }
7864                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7865                 {
7866                         blendfunc1 = t->customblendfunc[0];
7867                         blendfunc2 = t->customblendfunc[1];
7868                 }
7869                 else
7870                 {
7871                         blendfunc1 = GL_ONE;
7872                         blendfunc2 = GL_ZERO;
7873                 }
7874                 // don't colormod evilblend textures
7875                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7876                         VectorSet(t->lightmapcolor, 1, 1, 1);
7877                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7878                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7879                 {
7880                         // fullbright is not affected by r_refdef.lightmapintensity
7881                         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]);
7882                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7883                                 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]);
7884                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7885                                 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]);
7886                 }
7887                 else
7888                 {
7889                         vec3_t ambientcolor;
7890                         float colorscale;
7891                         // set the color tint used for lights affecting this surface
7892                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7893                         colorscale = 2;
7894                         // q3bsp has no lightmap updates, so the lightstylevalue that
7895                         // would normally be baked into the lightmap must be
7896                         // applied to the color
7897                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7898                         if (model->type == mod_brushq3)
7899                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7900                         colorscale *= r_refdef.lightmapintensity;
7901                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7902                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7903                         // basic lit geometry
7904                         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]);
7905                         // add pants/shirt if needed
7906                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7907                                 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]);
7908                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7909                                 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]);
7910                         // now add ambient passes if needed
7911                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7912                         {
7913                                 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]);
7914                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7915                                         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]);
7916                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7917                                         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]);
7918                         }
7919                 }
7920                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7921                         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]);
7922                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7923                 {
7924                         // if this is opaque use alpha blend which will darken the earlier
7925                         // passes cheaply.
7926                         //
7927                         // if this is an alpha blended material, all the earlier passes
7928                         // were darkened by fog already, so we only need to add the fog
7929                         // color ontop through the fog mask texture
7930                         //
7931                         // if this is an additive blended material, all the earlier passes
7932                         // were darkened by fog already, and we should not add fog color
7933                         // (because the background was not darkened, there is no fog color
7934                         // that was lost behind it).
7935                         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]);
7936                 }
7937         }
7938
7939         return t->currentframe;
7940 }
7941
7942 rsurfacestate_t rsurface;
7943
7944 void RSurf_ActiveWorldEntity(void)
7945 {
7946         dp_model_t *model = r_refdef.scene.worldmodel;
7947         //if (rsurface.entity == r_refdef.scene.worldentity)
7948         //      return;
7949         rsurface.entity = r_refdef.scene.worldentity;
7950         rsurface.skeleton = NULL;
7951         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7952         rsurface.ent_skinnum = 0;
7953         rsurface.ent_qwskin = -1;
7954         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7955         rsurface.shadertime = r_refdef.scene.time;
7956         rsurface.matrix = identitymatrix;
7957         rsurface.inversematrix = identitymatrix;
7958         rsurface.matrixscale = 1;
7959         rsurface.inversematrixscale = 1;
7960         R_EntityMatrix(&identitymatrix);
7961         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7962         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7963         rsurface.fograngerecip = r_refdef.fograngerecip;
7964         rsurface.fogheightfade = r_refdef.fogheightfade;
7965         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7966         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7967         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7968         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7969         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7970         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7971         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7972         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7973         rsurface.colormod[3] = 1;
7974         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);
7975         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7976         rsurface.frameblend[0].lerp = 1;
7977         rsurface.ent_alttextures = false;
7978         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7979         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7980         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7981         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7982         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7983         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7984         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7986         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7987         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7988         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7989         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7990         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7991         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7992         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7993         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7994         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7995         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7996         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7997         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7998         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7999         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8000         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8001         rsurface.modelelement3i = model->surfmesh.data_element3i;
8002         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8003         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8004         rsurface.modelelement3s = model->surfmesh.data_element3s;
8005         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8006         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8007         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8008         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8009         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8010         rsurface.modelsurfaces = model->data_surfaces;
8011         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8012         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8013         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8014         rsurface.modelgeneratedvertex = false;
8015         rsurface.batchgeneratedvertex = false;
8016         rsurface.batchfirstvertex = 0;
8017         rsurface.batchnumvertices = 0;
8018         rsurface.batchfirsttriangle = 0;
8019         rsurface.batchnumtriangles = 0;
8020         rsurface.batchvertex3f  = NULL;
8021         rsurface.batchvertex3f_vertexbuffer = NULL;
8022         rsurface.batchvertex3f_bufferoffset = 0;
8023         rsurface.batchsvector3f = NULL;
8024         rsurface.batchsvector3f_vertexbuffer = NULL;
8025         rsurface.batchsvector3f_bufferoffset = 0;
8026         rsurface.batchtvector3f = NULL;
8027         rsurface.batchtvector3f_vertexbuffer = NULL;
8028         rsurface.batchtvector3f_bufferoffset = 0;
8029         rsurface.batchnormal3f  = NULL;
8030         rsurface.batchnormal3f_vertexbuffer = NULL;
8031         rsurface.batchnormal3f_bufferoffset = 0;
8032         rsurface.batchlightmapcolor4f = NULL;
8033         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8034         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8035         rsurface.batchtexcoordtexture2f = NULL;
8036         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8037         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8038         rsurface.batchtexcoordlightmap2f = NULL;
8039         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8040         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8041         rsurface.batchvertexmesh = NULL;
8042         rsurface.batchvertexmeshbuffer = NULL;
8043         rsurface.batchvertex3fbuffer = NULL;
8044         rsurface.batchelement3i = NULL;
8045         rsurface.batchelement3i_indexbuffer = NULL;
8046         rsurface.batchelement3i_bufferoffset = 0;
8047         rsurface.batchelement3s = NULL;
8048         rsurface.batchelement3s_indexbuffer = NULL;
8049         rsurface.batchelement3s_bufferoffset = 0;
8050         rsurface.passcolor4f = NULL;
8051         rsurface.passcolor4f_vertexbuffer = NULL;
8052         rsurface.passcolor4f_bufferoffset = 0;
8053 }
8054
8055 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8056 {
8057         dp_model_t *model = ent->model;
8058         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8059         //      return;
8060         rsurface.entity = (entity_render_t *)ent;
8061         rsurface.skeleton = ent->skeleton;
8062         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8063         rsurface.ent_skinnum = ent->skinnum;
8064         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;
8065         rsurface.ent_flags = ent->flags;
8066         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8067         rsurface.matrix = ent->matrix;
8068         rsurface.inversematrix = ent->inversematrix;
8069         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8070         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8071         R_EntityMatrix(&rsurface.matrix);
8072         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8073         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8074         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8075         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8076         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8077         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8078         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8079         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8080         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8081         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8082         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8083         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8084         rsurface.colormod[3] = ent->alpha;
8085         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8086         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8087         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8088         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8089         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8090         if (ent->model->brush.submodel && !prepass)
8091         {
8092                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8093                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8094         }
8095         if (model->surfmesh.isanimated && model->AnimateVertices)
8096         {
8097                 if (ent->animcache_vertex3f)
8098                 {
8099                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8100                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8101                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8102                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8103                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8104                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8105                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8106                 }
8107                 else if (wanttangents)
8108                 {
8109                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8110                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8111                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8112                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8113                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8114                         rsurface.modelvertexmesh = NULL;
8115                         rsurface.modelvertexmeshbuffer = NULL;
8116                         rsurface.modelvertex3fbuffer = NULL;
8117                 }
8118                 else if (wantnormals)
8119                 {
8120                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8121                         rsurface.modelsvector3f = NULL;
8122                         rsurface.modeltvector3f = NULL;
8123                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8124                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8125                         rsurface.modelvertexmesh = NULL;
8126                         rsurface.modelvertexmeshbuffer = NULL;
8127                         rsurface.modelvertex3fbuffer = NULL;
8128                 }
8129                 else
8130                 {
8131                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8132                         rsurface.modelsvector3f = NULL;
8133                         rsurface.modeltvector3f = NULL;
8134                         rsurface.modelnormal3f = NULL;
8135                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8136                         rsurface.modelvertexmesh = NULL;
8137                         rsurface.modelvertexmeshbuffer = NULL;
8138                         rsurface.modelvertex3fbuffer = NULL;
8139                 }
8140                 rsurface.modelvertex3f_vertexbuffer = 0;
8141                 rsurface.modelvertex3f_bufferoffset = 0;
8142                 rsurface.modelsvector3f_vertexbuffer = 0;
8143                 rsurface.modelsvector3f_bufferoffset = 0;
8144                 rsurface.modeltvector3f_vertexbuffer = 0;
8145                 rsurface.modeltvector3f_bufferoffset = 0;
8146                 rsurface.modelnormal3f_vertexbuffer = 0;
8147                 rsurface.modelnormal3f_bufferoffset = 0;
8148                 rsurface.modelgeneratedvertex = true;
8149         }
8150         else
8151         {
8152                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8153                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8154                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8155                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8156                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8157                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8158                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8159                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8160                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8161                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8162                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8163                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8164                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8165                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8166                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8167                 rsurface.modelgeneratedvertex = false;
8168         }
8169         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8170         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8171         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8172         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8173         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8174         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8175         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8176         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8177         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8178         rsurface.modelelement3i = model->surfmesh.data_element3i;
8179         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8180         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8181         rsurface.modelelement3s = model->surfmesh.data_element3s;
8182         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8183         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8184         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8185         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8186         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8187         rsurface.modelsurfaces = model->data_surfaces;
8188         rsurface.batchgeneratedvertex = false;
8189         rsurface.batchfirstvertex = 0;
8190         rsurface.batchnumvertices = 0;
8191         rsurface.batchfirsttriangle = 0;
8192         rsurface.batchnumtriangles = 0;
8193         rsurface.batchvertex3f  = NULL;
8194         rsurface.batchvertex3f_vertexbuffer = NULL;
8195         rsurface.batchvertex3f_bufferoffset = 0;
8196         rsurface.batchsvector3f = NULL;
8197         rsurface.batchsvector3f_vertexbuffer = NULL;
8198         rsurface.batchsvector3f_bufferoffset = 0;
8199         rsurface.batchtvector3f = NULL;
8200         rsurface.batchtvector3f_vertexbuffer = NULL;
8201         rsurface.batchtvector3f_bufferoffset = 0;
8202         rsurface.batchnormal3f  = NULL;
8203         rsurface.batchnormal3f_vertexbuffer = NULL;
8204         rsurface.batchnormal3f_bufferoffset = 0;
8205         rsurface.batchlightmapcolor4f = NULL;
8206         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8207         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8208         rsurface.batchtexcoordtexture2f = NULL;
8209         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8210         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8211         rsurface.batchtexcoordlightmap2f = NULL;
8212         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8213         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8214         rsurface.batchvertexmesh = NULL;
8215         rsurface.batchvertexmeshbuffer = NULL;
8216         rsurface.batchvertex3fbuffer = NULL;
8217         rsurface.batchelement3i = NULL;
8218         rsurface.batchelement3i_indexbuffer = NULL;
8219         rsurface.batchelement3i_bufferoffset = 0;
8220         rsurface.batchelement3s = NULL;
8221         rsurface.batchelement3s_indexbuffer = NULL;
8222         rsurface.batchelement3s_bufferoffset = 0;
8223         rsurface.passcolor4f = NULL;
8224         rsurface.passcolor4f_vertexbuffer = NULL;
8225         rsurface.passcolor4f_bufferoffset = 0;
8226 }
8227
8228 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)
8229 {
8230         rsurface.entity = r_refdef.scene.worldentity;
8231         rsurface.skeleton = NULL;
8232         rsurface.ent_skinnum = 0;
8233         rsurface.ent_qwskin = -1;
8234         rsurface.ent_flags = entflags;
8235         rsurface.shadertime = r_refdef.scene.time - shadertime;
8236         rsurface.modelnumvertices = numvertices;
8237         rsurface.modelnumtriangles = numtriangles;
8238         rsurface.matrix = *matrix;
8239         rsurface.inversematrix = *inversematrix;
8240         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8241         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8242         R_EntityMatrix(&rsurface.matrix);
8243         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8244         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8245         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8246         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8247         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8248         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8249         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8250         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8251         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8252         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8253         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8254         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8255         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);
8256         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8257         rsurface.frameblend[0].lerp = 1;
8258         rsurface.ent_alttextures = false;
8259         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8260         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8261         if (wanttangents)
8262         {
8263                 rsurface.modelvertex3f = (float *)vertex3f;
8264                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8265                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8266                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8267         }
8268         else if (wantnormals)
8269         {
8270                 rsurface.modelvertex3f = (float *)vertex3f;
8271                 rsurface.modelsvector3f = NULL;
8272                 rsurface.modeltvector3f = NULL;
8273                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8274         }
8275         else
8276         {
8277                 rsurface.modelvertex3f = (float *)vertex3f;
8278                 rsurface.modelsvector3f = NULL;
8279                 rsurface.modeltvector3f = NULL;
8280                 rsurface.modelnormal3f = NULL;
8281         }
8282         rsurface.modelvertexmesh = NULL;
8283         rsurface.modelvertexmeshbuffer = NULL;
8284         rsurface.modelvertex3fbuffer = NULL;
8285         rsurface.modelvertex3f_vertexbuffer = 0;
8286         rsurface.modelvertex3f_bufferoffset = 0;
8287         rsurface.modelsvector3f_vertexbuffer = 0;
8288         rsurface.modelsvector3f_bufferoffset = 0;
8289         rsurface.modeltvector3f_vertexbuffer = 0;
8290         rsurface.modeltvector3f_bufferoffset = 0;
8291         rsurface.modelnormal3f_vertexbuffer = 0;
8292         rsurface.modelnormal3f_bufferoffset = 0;
8293         rsurface.modelgeneratedvertex = true;
8294         rsurface.modellightmapcolor4f  = (float *)color4f;
8295         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8296         rsurface.modellightmapcolor4f_bufferoffset = 0;
8297         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8298         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8299         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8300         rsurface.modeltexcoordlightmap2f  = NULL;
8301         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8302         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8303         rsurface.modelelement3i = (int *)element3i;
8304         rsurface.modelelement3i_indexbuffer = NULL;
8305         rsurface.modelelement3i_bufferoffset = 0;
8306         rsurface.modelelement3s = (unsigned short *)element3s;
8307         rsurface.modelelement3s_indexbuffer = NULL;
8308         rsurface.modelelement3s_bufferoffset = 0;
8309         rsurface.modellightmapoffsets = NULL;
8310         rsurface.modelsurfaces = NULL;
8311         rsurface.batchgeneratedvertex = false;
8312         rsurface.batchfirstvertex = 0;
8313         rsurface.batchnumvertices = 0;
8314         rsurface.batchfirsttriangle = 0;
8315         rsurface.batchnumtriangles = 0;
8316         rsurface.batchvertex3f  = NULL;
8317         rsurface.batchvertex3f_vertexbuffer = NULL;
8318         rsurface.batchvertex3f_bufferoffset = 0;
8319         rsurface.batchsvector3f = NULL;
8320         rsurface.batchsvector3f_vertexbuffer = NULL;
8321         rsurface.batchsvector3f_bufferoffset = 0;
8322         rsurface.batchtvector3f = NULL;
8323         rsurface.batchtvector3f_vertexbuffer = NULL;
8324         rsurface.batchtvector3f_bufferoffset = 0;
8325         rsurface.batchnormal3f  = NULL;
8326         rsurface.batchnormal3f_vertexbuffer = NULL;
8327         rsurface.batchnormal3f_bufferoffset = 0;
8328         rsurface.batchlightmapcolor4f = NULL;
8329         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8330         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8331         rsurface.batchtexcoordtexture2f = NULL;
8332         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8333         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8334         rsurface.batchtexcoordlightmap2f = NULL;
8335         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8336         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8337         rsurface.batchvertexmesh = NULL;
8338         rsurface.batchvertexmeshbuffer = NULL;
8339         rsurface.batchvertex3fbuffer = NULL;
8340         rsurface.batchelement3i = NULL;
8341         rsurface.batchelement3i_indexbuffer = NULL;
8342         rsurface.batchelement3i_bufferoffset = 0;
8343         rsurface.batchelement3s = NULL;
8344         rsurface.batchelement3s_indexbuffer = NULL;
8345         rsurface.batchelement3s_bufferoffset = 0;
8346         rsurface.passcolor4f = NULL;
8347         rsurface.passcolor4f_vertexbuffer = NULL;
8348         rsurface.passcolor4f_bufferoffset = 0;
8349
8350         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8351         {
8352                 if ((wantnormals || wanttangents) && !normal3f)
8353                 {
8354                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8355                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8356                 }
8357                 if (wanttangents && !svector3f)
8358                 {
8359                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8360                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8361                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8362                 }
8363         }
8364 }
8365
8366 float RSurf_FogPoint(const float *v)
8367 {
8368         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8369         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8370         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8371         float FogHeightFade = r_refdef.fogheightfade;
8372         float fogfrac;
8373         unsigned int fogmasktableindex;
8374         if (r_refdef.fogplaneviewabove)
8375                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8376         else
8377                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8378         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8379         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8380 }
8381
8382 float RSurf_FogVertex(const float *v)
8383 {
8384         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8385         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8386         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8387         float FogHeightFade = rsurface.fogheightfade;
8388         float fogfrac;
8389         unsigned int fogmasktableindex;
8390         if (r_refdef.fogplaneviewabove)
8391                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8392         else
8393                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8394         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8395         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8396 }
8397
8398 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8399 {
8400         int i;
8401         for (i = 0;i < numelements;i++)
8402                 outelement3i[i] = inelement3i[i] + adjust;
8403 }
8404
8405 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8406 extern cvar_t gl_vbo;
8407 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8408 {
8409         int deformindex;
8410         int firsttriangle;
8411         int numtriangles;
8412         int firstvertex;
8413         int endvertex;
8414         int numvertices;
8415         int surfacefirsttriangle;
8416         int surfacenumtriangles;
8417         int surfacefirstvertex;
8418         int surfaceendvertex;
8419         int surfacenumvertices;
8420         int batchnumvertices;
8421         int batchnumtriangles;
8422         int needsupdate;
8423         int i, j;
8424         qboolean gaps;
8425         qboolean dynamicvertex;
8426         float amplitude;
8427         float animpos;
8428         float scale;
8429         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8430         float waveparms[4];
8431         q3shaderinfo_deform_t *deform;
8432         const msurface_t *surface, *firstsurface;
8433         r_vertexmesh_t *vertexmesh;
8434         if (!texturenumsurfaces)
8435                 return;
8436         // find vertex range of this surface batch
8437         gaps = false;
8438         firstsurface = texturesurfacelist[0];
8439         firsttriangle = firstsurface->num_firsttriangle;
8440         batchnumvertices = 0;
8441         batchnumtriangles = 0;
8442         firstvertex = endvertex = firstsurface->num_firstvertex;
8443         for (i = 0;i < texturenumsurfaces;i++)
8444         {
8445                 surface = texturesurfacelist[i];
8446                 if (surface != firstsurface + i)
8447                         gaps = true;
8448                 surfacefirstvertex = surface->num_firstvertex;
8449                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8450                 surfacenumvertices = surface->num_vertices;
8451                 surfacenumtriangles = surface->num_triangles;
8452                 if (firstvertex > surfacefirstvertex)
8453                         firstvertex = surfacefirstvertex;
8454                 if (endvertex < surfaceendvertex)
8455                         endvertex = surfaceendvertex;
8456                 batchnumvertices += surfacenumvertices;
8457                 batchnumtriangles += surfacenumtriangles;
8458         }
8459
8460         // we now know the vertex range used, and if there are any gaps in it
8461         rsurface.batchfirstvertex = firstvertex;
8462         rsurface.batchnumvertices = endvertex - firstvertex;
8463         rsurface.batchfirsttriangle = firsttriangle;
8464         rsurface.batchnumtriangles = batchnumtriangles;
8465
8466         // this variable holds flags for which properties have been updated that
8467         // may require regenerating vertexmesh array...
8468         needsupdate = 0;
8469
8470         // check if any dynamic vertex processing must occur
8471         dynamicvertex = false;
8472
8473         // if there is a chance of animated vertex colors, it's a dynamic batch
8474         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8475         {
8476                 dynamicvertex = true;
8477                 batchneed |= BATCHNEED_NOGAPS;
8478                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8479         }
8480
8481         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8482         {
8483                 switch (deform->deform)
8484                 {
8485                 default:
8486                 case Q3DEFORM_PROJECTIONSHADOW:
8487                 case Q3DEFORM_TEXT0:
8488                 case Q3DEFORM_TEXT1:
8489                 case Q3DEFORM_TEXT2:
8490                 case Q3DEFORM_TEXT3:
8491                 case Q3DEFORM_TEXT4:
8492                 case Q3DEFORM_TEXT5:
8493                 case Q3DEFORM_TEXT6:
8494                 case Q3DEFORM_TEXT7:
8495                 case Q3DEFORM_NONE:
8496                         break;
8497                 case Q3DEFORM_AUTOSPRITE:
8498                         dynamicvertex = true;
8499                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8500                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8501                         break;
8502                 case Q3DEFORM_AUTOSPRITE2:
8503                         dynamicvertex = true;
8504                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8505                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8506                         break;
8507                 case Q3DEFORM_NORMAL:
8508                         dynamicvertex = true;
8509                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8510                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8511                         break;
8512                 case Q3DEFORM_WAVE:
8513                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8514                                 break; // if wavefunc is a nop, ignore this transform
8515                         dynamicvertex = true;
8516                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8517                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8518                         break;
8519                 case Q3DEFORM_BULGE:
8520                         dynamicvertex = true;
8521                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8522                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8523                         break;
8524                 case Q3DEFORM_MOVE:
8525                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8526                                 break; // if wavefunc is a nop, ignore this transform
8527                         dynamicvertex = true;
8528                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8529                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8530                         break;
8531                 }
8532         }
8533         switch(rsurface.texture->tcgen.tcgen)
8534         {
8535         default:
8536         case Q3TCGEN_TEXTURE:
8537                 break;
8538         case Q3TCGEN_LIGHTMAP:
8539                 dynamicvertex = true;
8540                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8541                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8542                 break;
8543         case Q3TCGEN_VECTOR:
8544                 dynamicvertex = true;
8545                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8546                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8547                 break;
8548         case Q3TCGEN_ENVIRONMENT:
8549                 dynamicvertex = true;
8550                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8551                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8552                 break;
8553         }
8554         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8555         {
8556                 dynamicvertex = true;
8557                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8558                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8559         }
8560
8561         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8562         {
8563                 dynamicvertex = true;
8564                 batchneed |= BATCHNEED_NOGAPS;
8565                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8566         }
8567
8568         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8569         {
8570                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8571                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8572                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8573                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8574                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8575                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8576                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8577         }
8578
8579         // when the model data has no vertex buffer (dynamic mesh), we need to
8580         // eliminate gaps
8581         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8582                 batchneed |= BATCHNEED_NOGAPS;
8583
8584         // if needsupdate, we have to do a dynamic vertex batch for sure
8585         if (needsupdate & batchneed)
8586                 dynamicvertex = true;
8587
8588         // see if we need to build vertexmesh from arrays
8589         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8590                 dynamicvertex = true;
8591
8592         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8593         // also some drivers strongly dislike firstvertex
8594         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8595                 dynamicvertex = true;
8596
8597         rsurface.batchvertex3f = rsurface.modelvertex3f;
8598         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8599         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8600         rsurface.batchsvector3f = rsurface.modelsvector3f;
8601         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8602         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8603         rsurface.batchtvector3f = rsurface.modeltvector3f;
8604         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8605         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8606         rsurface.batchnormal3f = rsurface.modelnormal3f;
8607         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8608         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8609         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8610         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8611         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8612         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8613         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8614         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8615         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8616         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8617         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8618         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8619         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8620         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8621         rsurface.batchelement3i = rsurface.modelelement3i;
8622         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8623         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8624         rsurface.batchelement3s = rsurface.modelelement3s;
8625         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8626         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8627
8628         // if any dynamic vertex processing has to occur in software, we copy the
8629         // entire surface list together before processing to rebase the vertices
8630         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8631         //
8632         // if any gaps exist and we do not have a static vertex buffer, we have to
8633         // copy the surface list together to avoid wasting upload bandwidth on the
8634         // vertices in the gaps.
8635         //
8636         // if gaps exist and we have a static vertex buffer, we still have to
8637         // combine the index buffer ranges into one dynamic index buffer.
8638         //
8639         // in all cases we end up with data that can be drawn in one call.
8640
8641         if (!dynamicvertex)
8642         {
8643                 // static vertex data, just set pointers...
8644                 rsurface.batchgeneratedvertex = false;
8645                 // if there are gaps, we want to build a combined index buffer,
8646                 // otherwise use the original static buffer with an appropriate offset
8647                 if (gaps)
8648                 {
8649                         // build a new triangle elements array for this batch
8650                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8651                         rsurface.batchfirsttriangle = 0;
8652                         numtriangles = 0;
8653                         for (i = 0;i < texturenumsurfaces;i++)
8654                         {
8655                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8656                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8657                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8658                                 numtriangles += surfacenumtriangles;
8659                         }
8660                         rsurface.batchelement3i_indexbuffer = NULL;
8661                         rsurface.batchelement3i_bufferoffset = 0;
8662                         rsurface.batchelement3s = NULL;
8663                         rsurface.batchelement3s_indexbuffer = NULL;
8664                         rsurface.batchelement3s_bufferoffset = 0;
8665                         if (endvertex <= 65536)
8666                         {
8667                                 // make a 16bit (unsigned short) index array if possible
8668                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8669                                 for (i = 0;i < numtriangles*3;i++)
8670                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8671                         }
8672                 }
8673                 return;
8674         }
8675
8676         // something needs software processing, do it for real...
8677         // we only directly handle separate array data in this case and then
8678         // generate interleaved data if needed...
8679         rsurface.batchgeneratedvertex = true;
8680
8681         // now copy the vertex data into a combined array and make an index array
8682         // (this is what Quake3 does all the time)
8683         //if (gaps || rsurface.batchfirstvertex)
8684         {
8685                 rsurface.batchvertex3fbuffer = NULL;
8686                 rsurface.batchvertexmesh = NULL;
8687                 rsurface.batchvertexmeshbuffer = NULL;
8688                 rsurface.batchvertex3f = NULL;
8689                 rsurface.batchvertex3f_vertexbuffer = NULL;
8690                 rsurface.batchvertex3f_bufferoffset = 0;
8691                 rsurface.batchsvector3f = NULL;
8692                 rsurface.batchsvector3f_vertexbuffer = NULL;
8693                 rsurface.batchsvector3f_bufferoffset = 0;
8694                 rsurface.batchtvector3f = NULL;
8695                 rsurface.batchtvector3f_vertexbuffer = NULL;
8696                 rsurface.batchtvector3f_bufferoffset = 0;
8697                 rsurface.batchnormal3f = NULL;
8698                 rsurface.batchnormal3f_vertexbuffer = NULL;
8699                 rsurface.batchnormal3f_bufferoffset = 0;
8700                 rsurface.batchlightmapcolor4f = NULL;
8701                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8702                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8703                 rsurface.batchtexcoordtexture2f = NULL;
8704                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8705                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8706                 rsurface.batchtexcoordlightmap2f = NULL;
8707                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8708                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8709                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8710                 rsurface.batchelement3i_indexbuffer = NULL;
8711                 rsurface.batchelement3i_bufferoffset = 0;
8712                 rsurface.batchelement3s = NULL;
8713                 rsurface.batchelement3s_indexbuffer = NULL;
8714                 rsurface.batchelement3s_bufferoffset = 0;
8715                 // we'll only be setting up certain arrays as needed
8716                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8717                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8718                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8719                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8720                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8721                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8722                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8723                 {
8724                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8725                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8726                 }
8727                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8728                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8729                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8730                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8731                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8732                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8733                 numvertices = 0;
8734                 numtriangles = 0;
8735                 for (i = 0;i < texturenumsurfaces;i++)
8736                 {
8737                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8738                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8739                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8740                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8741                         // copy only the data requested
8742                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8743                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8744                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8745                         {
8746                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8747                                 {
8748                                         if (rsurface.batchvertex3f)
8749                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8750                                         else
8751                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8752                                 }
8753                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8754                                 {
8755                                         if (rsurface.modelnormal3f)
8756                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8757                                         else
8758                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8759                                 }
8760                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8761                                 {
8762                                         if (rsurface.modelsvector3f)
8763                                         {
8764                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8765                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8766                                         }
8767                                         else
8768                                         {
8769                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8770                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8771                                         }
8772                                 }
8773                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8774                                 {
8775                                         if (rsurface.modellightmapcolor4f)
8776                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8777                                         else
8778                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8779                                 }
8780                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8781                                 {
8782                                         if (rsurface.modeltexcoordtexture2f)
8783                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8784                                         else
8785                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8786                                 }
8787                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8788                                 {
8789                                         if (rsurface.modeltexcoordlightmap2f)
8790                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8791                                         else
8792                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8793                                 }
8794                         }
8795                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8796                         numvertices += surfacenumvertices;
8797                         numtriangles += surfacenumtriangles;
8798                 }
8799
8800                 // generate a 16bit index array as well if possible
8801                 // (in general, dynamic batches fit)
8802                 if (numvertices <= 65536)
8803                 {
8804                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8805                         for (i = 0;i < numtriangles*3;i++)
8806                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8807                 }
8808
8809                 // since we've copied everything, the batch now starts at 0
8810                 rsurface.batchfirstvertex = 0;
8811                 rsurface.batchnumvertices = batchnumvertices;
8812                 rsurface.batchfirsttriangle = 0;
8813                 rsurface.batchnumtriangles = batchnumtriangles;
8814         }
8815
8816         // q1bsp surfaces rendered in vertex color mode have to have colors
8817         // calculated based on lightstyles
8818         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8819         {
8820                 // generate color arrays for the surfaces in this list
8821                 int c[4];
8822                 int scale;
8823                 int size3;
8824                 const int *offsets;
8825                 const unsigned char *lm;
8826                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8827                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8828                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8829                 numvertices = 0;
8830                 for (i = 0;i < texturenumsurfaces;i++)
8831                 {
8832                         surface = texturesurfacelist[i];
8833                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8834                         surfacenumvertices = surface->num_vertices;
8835                         if (surface->lightmapinfo->samples)
8836                         {
8837                                 for (j = 0;j < surfacenumvertices;j++)
8838                                 {
8839                                         lm = surface->lightmapinfo->samples + offsets[j];
8840                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8841                                         VectorScale(lm, scale, c);
8842                                         if (surface->lightmapinfo->styles[1] != 255)
8843                                         {
8844                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8845                                                 lm += size3;
8846                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8847                                                 VectorMA(c, scale, lm, c);
8848                                                 if (surface->lightmapinfo->styles[2] != 255)
8849                                                 {
8850                                                         lm += size3;
8851                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8852                                                         VectorMA(c, scale, lm, c);
8853                                                         if (surface->lightmapinfo->styles[3] != 255)
8854                                                         {
8855                                                                 lm += size3;
8856                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8857                                                                 VectorMA(c, scale, lm, c);
8858                                                         }
8859                                                 }
8860                                         }
8861                                         c[0] >>= 7;
8862                                         c[1] >>= 7;
8863                                         c[2] >>= 7;
8864                                         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);
8865                                         numvertices++;
8866                                 }
8867                         }
8868                         else
8869                         {
8870                                 for (j = 0;j < surfacenumvertices;j++)
8871                                 {
8872                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8873                                         numvertices++;
8874                                 }
8875                         }
8876                 }
8877         }
8878
8879         // if vertices are deformed (sprite flares and things in maps, possibly
8880         // water waves, bulges and other deformations), modify the copied vertices
8881         // in place
8882         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8883         {
8884                 switch (deform->deform)
8885                 {
8886                 default:
8887                 case Q3DEFORM_PROJECTIONSHADOW:
8888                 case Q3DEFORM_TEXT0:
8889                 case Q3DEFORM_TEXT1:
8890                 case Q3DEFORM_TEXT2:
8891                 case Q3DEFORM_TEXT3:
8892                 case Q3DEFORM_TEXT4:
8893                 case Q3DEFORM_TEXT5:
8894                 case Q3DEFORM_TEXT6:
8895                 case Q3DEFORM_TEXT7:
8896                 case Q3DEFORM_NONE:
8897                         break;
8898                 case Q3DEFORM_AUTOSPRITE:
8899                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8900                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8901                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8902                         VectorNormalize(newforward);
8903                         VectorNormalize(newright);
8904                         VectorNormalize(newup);
8905 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8906 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8907 //                      rsurface.batchvertex3f_bufferoffset = 0;
8908 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8909 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8910 //                      rsurface.batchsvector3f_bufferoffset = 0;
8911 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8912 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8913 //                      rsurface.batchtvector3f_bufferoffset = 0;
8914 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8915 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8916 //                      rsurface.batchnormal3f_bufferoffset = 0;
8917                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8918                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8919                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8920                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8921                                 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);
8922                         // a single autosprite surface can contain multiple sprites...
8923                         for (j = 0;j < batchnumvertices - 3;j += 4)
8924                         {
8925                                 VectorClear(center);
8926                                 for (i = 0;i < 4;i++)
8927                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8928                                 VectorScale(center, 0.25f, center);
8929                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8930                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8931                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8932                                 for (i = 0;i < 4;i++)
8933                                 {
8934                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8935                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8936                                 }
8937                         }
8938                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8939                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8940                         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);
8941                         break;
8942                 case Q3DEFORM_AUTOSPRITE2:
8943                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8944                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8945                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8946                         VectorNormalize(newforward);
8947                         VectorNormalize(newright);
8948                         VectorNormalize(newup);
8949 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8950 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8951 //                      rsurface.batchvertex3f_bufferoffset = 0;
8952                         {
8953                                 const float *v1, *v2;
8954                                 vec3_t start, end;
8955                                 float f, l;
8956                                 struct
8957                                 {
8958                                         float length2;
8959                                         const float *v1;
8960                                         const float *v2;
8961                                 }
8962                                 shortest[2];
8963                                 memset(shortest, 0, sizeof(shortest));
8964                                 // a single autosprite surface can contain multiple sprites...
8965                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8966                                 {
8967                                         VectorClear(center);
8968                                         for (i = 0;i < 4;i++)
8969                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8970                                         VectorScale(center, 0.25f, center);
8971                                         // find the two shortest edges, then use them to define the
8972                                         // axis vectors for rotating around the central axis
8973                                         for (i = 0;i < 6;i++)
8974                                         {
8975                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8976                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8977                                                 l = VectorDistance2(v1, v2);
8978                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8979                                                 if (v1[2] != v2[2])
8980                                                         l += (1.0f / 1024.0f);
8981                                                 if (shortest[0].length2 > l || i == 0)
8982                                                 {
8983                                                         shortest[1] = shortest[0];
8984                                                         shortest[0].length2 = l;
8985                                                         shortest[0].v1 = v1;
8986                                                         shortest[0].v2 = v2;
8987                                                 }
8988                                                 else if (shortest[1].length2 > l || i == 1)
8989                                                 {
8990                                                         shortest[1].length2 = l;
8991                                                         shortest[1].v1 = v1;
8992                                                         shortest[1].v2 = v2;
8993                                                 }
8994                                         }
8995                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8996                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8997                                         // this calculates the right vector from the shortest edge
8998                                         // and the up vector from the edge midpoints
8999                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9000                                         VectorNormalize(right);
9001                                         VectorSubtract(end, start, up);
9002                                         VectorNormalize(up);
9003                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9004                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9005                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9006                                         VectorNegate(forward, forward);
9007                                         VectorReflect(forward, 0, up, forward);
9008                                         VectorNormalize(forward);
9009                                         CrossProduct(up, forward, newright);
9010                                         VectorNormalize(newright);
9011                                         // rotate the quad around the up axis vector, this is made
9012                                         // especially easy by the fact we know the quad is flat,
9013                                         // so we only have to subtract the center position and
9014                                         // measure distance along the right vector, and then
9015                                         // multiply that by the newright vector and add back the
9016                                         // center position
9017                                         // we also need to subtract the old position to undo the
9018                                         // displacement from the center, which we do with a
9019                                         // DotProduct, the subtraction/addition of center is also
9020                                         // optimized into DotProducts here
9021                                         l = DotProduct(right, center);
9022                                         for (i = 0;i < 4;i++)
9023                                         {
9024                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9025                                                 f = DotProduct(right, v1) - l;
9026                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9027                                         }
9028                                 }
9029                         }
9030                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9031                         {
9032 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9033 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9034 //                              rsurface.batchnormal3f_bufferoffset = 0;
9035                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9036                         }
9037                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9038                         {
9039 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9040 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9041 //                              rsurface.batchsvector3f_bufferoffset = 0;
9042 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9043 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9044 //                              rsurface.batchtvector3f_bufferoffset = 0;
9045                                 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);
9046                         }
9047                         break;
9048                 case Q3DEFORM_NORMAL:
9049                         // deform the normals to make reflections wavey
9050                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9051                         rsurface.batchnormal3f_vertexbuffer = NULL;
9052                         rsurface.batchnormal3f_bufferoffset = 0;
9053                         for (j = 0;j < batchnumvertices;j++)
9054                         {
9055                                 float vertex[3];
9056                                 float *normal = rsurface.batchnormal3f + 3*j;
9057                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9058                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9059                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9060                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9061                                 VectorNormalize(normal);
9062                         }
9063                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9064                         {
9065 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9066 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9067 //                              rsurface.batchsvector3f_bufferoffset = 0;
9068 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9069 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9070 //                              rsurface.batchtvector3f_bufferoffset = 0;
9071                                 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);
9072                         }
9073                         break;
9074                 case Q3DEFORM_WAVE:
9075                         // deform vertex array to make wavey water and flags and such
9076                         waveparms[0] = deform->waveparms[0];
9077                         waveparms[1] = deform->waveparms[1];
9078                         waveparms[2] = deform->waveparms[2];
9079                         waveparms[3] = deform->waveparms[3];
9080                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9081                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9082                         // this is how a divisor of vertex influence on deformation
9083                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9084                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9085 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9086 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9087 //                      rsurface.batchvertex3f_bufferoffset = 0;
9088 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9089 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9090 //                      rsurface.batchnormal3f_bufferoffset = 0;
9091                         for (j = 0;j < batchnumvertices;j++)
9092                         {
9093                                 // if the wavefunc depends on time, evaluate it per-vertex
9094                                 if (waveparms[3])
9095                                 {
9096                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9097                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9098                                 }
9099                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9100                         }
9101                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9102                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9103                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9104                         {
9105 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9106 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9107 //                              rsurface.batchsvector3f_bufferoffset = 0;
9108 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9109 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9110 //                              rsurface.batchtvector3f_bufferoffset = 0;
9111                                 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);
9112                         }
9113                         break;
9114                 case Q3DEFORM_BULGE:
9115                         // deform vertex array to make the surface have moving bulges
9116 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9117 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9118 //                      rsurface.batchvertex3f_bufferoffset = 0;
9119 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9120 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9121 //                      rsurface.batchnormal3f_bufferoffset = 0;
9122                         for (j = 0;j < batchnumvertices;j++)
9123                         {
9124                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9125                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9126                         }
9127                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9128                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9129                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9130                         {
9131 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9132 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9133 //                              rsurface.batchsvector3f_bufferoffset = 0;
9134 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9135 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9136 //                              rsurface.batchtvector3f_bufferoffset = 0;
9137                                 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);
9138                         }
9139                         break;
9140                 case Q3DEFORM_MOVE:
9141                         // deform vertex array
9142                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9143                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9144                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9145                         VectorScale(deform->parms, scale, waveparms);
9146 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9147 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9148 //                      rsurface.batchvertex3f_bufferoffset = 0;
9149                         for (j = 0;j < batchnumvertices;j++)
9150                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9151                         break;
9152                 }
9153         }
9154
9155         // generate texcoords based on the chosen texcoord source
9156         switch(rsurface.texture->tcgen.tcgen)
9157         {
9158         default:
9159         case Q3TCGEN_TEXTURE:
9160                 break;
9161         case Q3TCGEN_LIGHTMAP:
9162 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9163 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9164 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9165                 if (rsurface.batchtexcoordlightmap2f)
9166                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9167                 break;
9168         case Q3TCGEN_VECTOR:
9169 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9170 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9171 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9172                 for (j = 0;j < batchnumvertices;j++)
9173                 {
9174                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9175                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9176                 }
9177                 break;
9178         case Q3TCGEN_ENVIRONMENT:
9179                 // make environment reflections using a spheremap
9180                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9181                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9182                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9183                 for (j = 0;j < batchnumvertices;j++)
9184                 {
9185                         // identical to Q3A's method, but executed in worldspace so
9186                         // carried models can be shiny too
9187
9188                         float viewer[3], d, reflected[3], worldreflected[3];
9189
9190                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9191                         // VectorNormalize(viewer);
9192
9193                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9194
9195                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9196                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9197                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9198                         // note: this is proportinal to viewer, so we can normalize later
9199
9200                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9201                         VectorNormalize(worldreflected);
9202
9203                         // note: this sphere map only uses world x and z!
9204                         // so positive and negative y will LOOK THE SAME.
9205                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9206                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9207                 }
9208                 break;
9209         }
9210         // the only tcmod that needs software vertex processing is turbulent, so
9211         // check for it here and apply the changes if needed
9212         // and we only support that as the first one
9213         // (handling a mixture of turbulent and other tcmods would be problematic
9214         //  without punting it entirely to a software path)
9215         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9216         {
9217                 amplitude = rsurface.texture->tcmods[0].parms[1];
9218                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9219 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9220 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9221 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9222                 for (j = 0;j < batchnumvertices;j++)
9223                 {
9224                         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);
9225                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9226                 }
9227         }
9228
9229         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9230         {
9231                 // convert the modified arrays to vertex structs
9232 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9233 //              rsurface.batchvertexmeshbuffer = NULL;
9234                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9235                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9236                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9237                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9238                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9239                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9240                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9241                 {
9242                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9243                         {
9244                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9245                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9246                         }
9247                 }
9248                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9249                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9250                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9251                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9252                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9253                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9254                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9255                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9256                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9257         }
9258 }
9259
9260 void RSurf_DrawBatch(void)
9261 {
9262         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9263         // through the pipeline, killing it earlier in the pipeline would have
9264         // per-surface overhead rather than per-batch overhead, so it's best to
9265         // reject it here, before it hits glDraw.
9266         if (rsurface.batchnumtriangles == 0)
9267                 return;
9268 #if 0
9269         // batch debugging code
9270         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9271         {
9272                 int i;
9273                 int j;
9274                 int c;
9275                 const int *e;
9276                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9277                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9278                 {
9279                         c = e[i];
9280                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9281                         {
9282                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9283                                 {
9284                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9285                                                 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);
9286                                         break;
9287                                 }
9288                         }
9289                 }
9290         }
9291 #endif
9292         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);
9293 }
9294
9295 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9296 {
9297         // pick the closest matching water plane
9298         int planeindex, vertexindex, bestplaneindex = -1;
9299         float d, bestd;
9300         vec3_t vert;
9301         const float *v;
9302         r_waterstate_waterplane_t *p;
9303         qboolean prepared = false;
9304         bestd = 0;
9305         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9306         {
9307                 if(p->camera_entity != rsurface.texture->camera_entity)
9308                         continue;
9309                 d = 0;
9310                 if(!prepared)
9311                 {
9312                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9313                         prepared = true;
9314                         if(rsurface.batchnumvertices == 0)
9315                                 break;
9316                 }
9317                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9318                 {
9319                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9320                         d += fabs(PlaneDiff(vert, &p->plane));
9321                 }
9322                 if (bestd > d || bestplaneindex < 0)
9323                 {
9324                         bestd = d;
9325                         bestplaneindex = planeindex;
9326                 }
9327         }
9328         return bestplaneindex;
9329         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9330         // this situation though, as it might be better to render single larger
9331         // batches with useless stuff (backface culled for example) than to
9332         // render multiple smaller batches
9333 }
9334
9335 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9336 {
9337         int i;
9338         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9339         rsurface.passcolor4f_vertexbuffer = 0;
9340         rsurface.passcolor4f_bufferoffset = 0;
9341         for (i = 0;i < rsurface.batchnumvertices;i++)
9342                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9343 }
9344
9345 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9346 {
9347         int i;
9348         float f;
9349         const float *v;
9350         const float *c;
9351         float *c2;
9352         if (rsurface.passcolor4f)
9353         {
9354                 // generate color arrays
9355                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9356                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9357                 rsurface.passcolor4f_vertexbuffer = 0;
9358                 rsurface.passcolor4f_bufferoffset = 0;
9359                 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)
9360                 {
9361                         f = RSurf_FogVertex(v);
9362                         c2[0] = c[0] * f;
9363                         c2[1] = c[1] * f;
9364                         c2[2] = c[2] * f;
9365                         c2[3] = c[3];
9366                 }
9367         }
9368         else
9369         {
9370                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9371                 rsurface.passcolor4f_vertexbuffer = 0;
9372                 rsurface.passcolor4f_bufferoffset = 0;
9373                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9374                 {
9375                         f = RSurf_FogVertex(v);
9376                         c2[0] = f;
9377                         c2[1] = f;
9378                         c2[2] = f;
9379                         c2[3] = 1;
9380                 }
9381         }
9382 }
9383
9384 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9385 {
9386         int i;
9387         float f;
9388         const float *v;
9389         const float *c;
9390         float *c2;
9391         if (!rsurface.passcolor4f)
9392                 return;
9393         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9394         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9395         rsurface.passcolor4f_vertexbuffer = 0;
9396         rsurface.passcolor4f_bufferoffset = 0;
9397         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)
9398         {
9399                 f = RSurf_FogVertex(v);
9400                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9401                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9402                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9403                 c2[3] = c[3];
9404         }
9405 }
9406
9407 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9408 {
9409         int i;
9410         const float *c;
9411         float *c2;
9412         if (!rsurface.passcolor4f)
9413                 return;
9414         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9415         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9416         rsurface.passcolor4f_vertexbuffer = 0;
9417         rsurface.passcolor4f_bufferoffset = 0;
9418         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9419         {
9420                 c2[0] = c[0] * r;
9421                 c2[1] = c[1] * g;
9422                 c2[2] = c[2] * b;
9423                 c2[3] = c[3] * a;
9424         }
9425 }
9426
9427 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9428 {
9429         int i;
9430         const float *c;
9431         float *c2;
9432         if (!rsurface.passcolor4f)
9433                 return;
9434         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9435         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9436         rsurface.passcolor4f_vertexbuffer = 0;
9437         rsurface.passcolor4f_bufferoffset = 0;
9438         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9439         {
9440                 c2[0] = c[0] + r_refdef.scene.ambient;
9441                 c2[1] = c[1] + r_refdef.scene.ambient;
9442                 c2[2] = c[2] + r_refdef.scene.ambient;
9443                 c2[3] = c[3];
9444         }
9445 }
9446
9447 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9448 {
9449         // TODO: optimize
9450         rsurface.passcolor4f = NULL;
9451         rsurface.passcolor4f_vertexbuffer = 0;
9452         rsurface.passcolor4f_bufferoffset = 0;
9453         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9454         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9455         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9456         GL_Color(r, g, b, a);
9457         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9458         RSurf_DrawBatch();
9459 }
9460
9461 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9462 {
9463         // TODO: optimize applyfog && applycolor case
9464         // just apply fog if necessary, and tint the fog color array if necessary
9465         rsurface.passcolor4f = NULL;
9466         rsurface.passcolor4f_vertexbuffer = 0;
9467         rsurface.passcolor4f_bufferoffset = 0;
9468         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9469         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9470         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9471         GL_Color(r, g, b, a);
9472         RSurf_DrawBatch();
9473 }
9474
9475 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9476 {
9477         // TODO: optimize
9478         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9479         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9480         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9481         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9482         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9483         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9484         GL_Color(r, g, b, a);
9485         RSurf_DrawBatch();
9486 }
9487
9488 static void RSurf_DrawBatch_GL11_ClampColor(void)
9489 {
9490         int i;
9491         const float *c1;
9492         float *c2;
9493         if (!rsurface.passcolor4f)
9494                 return;
9495         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9496         {
9497                 c2[0] = bound(0.0f, c1[0], 1.0f);
9498                 c2[1] = bound(0.0f, c1[1], 1.0f);
9499                 c2[2] = bound(0.0f, c1[2], 1.0f);
9500                 c2[3] = bound(0.0f, c1[3], 1.0f);
9501         }
9502 }
9503
9504 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9505 {
9506         int i;
9507         float f;
9508         const float *v;
9509         const float *n;
9510         float *c;
9511         //vec3_t eyedir;
9512
9513         // fake shading
9514         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9515         rsurface.passcolor4f_vertexbuffer = 0;
9516         rsurface.passcolor4f_bufferoffset = 0;
9517         for (i = 0, 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)
9518         {
9519                 f = -DotProduct(r_refdef.view.forward, n);
9520                 f = max(0, f);
9521                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9522                 f *= r_refdef.lightmapintensity;
9523                 Vector4Set(c, f, f, f, 1);
9524         }
9525 }
9526
9527 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9528 {
9529         RSurf_DrawBatch_GL11_ApplyFakeLight();
9530         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9531         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9532         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9533         GL_Color(r, g, b, a);
9534         RSurf_DrawBatch();
9535 }
9536
9537 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9538 {
9539         int i;
9540         float f;
9541         float alpha;
9542         const float *v;
9543         const float *n;
9544         float *c;
9545         vec3_t ambientcolor;
9546         vec3_t diffusecolor;
9547         vec3_t lightdir;
9548         // TODO: optimize
9549         // model lighting
9550         VectorCopy(rsurface.modellight_lightdir, lightdir);
9551         f = 0.5f * r_refdef.lightmapintensity;
9552         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9553         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9554         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9555         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9556         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9557         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9558         alpha = *a;
9559         if (VectorLength2(diffusecolor) > 0)
9560         {
9561                 // q3-style directional shading
9562                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9563                 rsurface.passcolor4f_vertexbuffer = 0;
9564                 rsurface.passcolor4f_bufferoffset = 0;
9565                 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)
9566                 {
9567                         if ((f = DotProduct(n, lightdir)) > 0)
9568                                 VectorMA(ambientcolor, f, diffusecolor, c);
9569                         else
9570                                 VectorCopy(ambientcolor, c);
9571                         c[3] = alpha;
9572                 }
9573                 *r = 1;
9574                 *g = 1;
9575                 *b = 1;
9576                 *a = 1;
9577                 *applycolor = false;
9578         }
9579         else
9580         {
9581                 *r = ambientcolor[0];
9582                 *g = ambientcolor[1];
9583                 *b = ambientcolor[2];
9584                 rsurface.passcolor4f = NULL;
9585                 rsurface.passcolor4f_vertexbuffer = 0;
9586                 rsurface.passcolor4f_bufferoffset = 0;
9587         }
9588 }
9589
9590 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9591 {
9592         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9593         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9594         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9595         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9596         GL_Color(r, g, b, a);
9597         RSurf_DrawBatch();
9598 }
9599
9600 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9601 {
9602         int i;
9603         float f;
9604         const float *v;
9605         float *c;
9606
9607         // fake shading
9608         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9609         rsurface.passcolor4f_vertexbuffer = 0;
9610         rsurface.passcolor4f_bufferoffset = 0;
9611
9612         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9613         {
9614                 f = 1 - RSurf_FogVertex(v);
9615                 c[0] = r;
9616                 c[1] = g;
9617                 c[2] = b;
9618                 c[3] = f * a;
9619         }
9620 }
9621
9622 void RSurf_SetupDepthAndCulling(void)
9623 {
9624         // submodels are biased to avoid z-fighting with world surfaces that they
9625         // may be exactly overlapping (avoids z-fighting artifacts on certain
9626         // doors and things in Quake maps)
9627         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9628         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9629         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9630         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9631 }
9632
9633 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9634 {
9635         // transparent sky would be ridiculous
9636         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9637                 return;
9638         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9639         skyrenderlater = true;
9640         RSurf_SetupDepthAndCulling();
9641         GL_DepthMask(true);
9642         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9643         // skymasking on them, and Quake3 never did sky masking (unlike
9644         // software Quake and software Quake2), so disable the sky masking
9645         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9646         // and skymasking also looks very bad when noclipping outside the
9647         // level, so don't use it then either.
9648         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9649         {
9650                 R_Mesh_ResetTextureState();
9651                 if (skyrendermasked)
9652                 {
9653                         R_SetupShader_DepthOrShadow(false);
9654                         // depth-only (masking)
9655                         GL_ColorMask(0,0,0,0);
9656                         // just to make sure that braindead drivers don't draw
9657                         // anything despite that colormask...
9658                         GL_BlendFunc(GL_ZERO, GL_ONE);
9659                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9660                         if (rsurface.batchvertex3fbuffer)
9661                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9662                         else
9663                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9664                 }
9665                 else
9666                 {
9667                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9668                         // fog sky
9669                         GL_BlendFunc(GL_ONE, GL_ZERO);
9670                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9671                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9672                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9673                 }
9674                 RSurf_DrawBatch();
9675                 if (skyrendermasked)
9676                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9677         }
9678         R_Mesh_ResetTextureState();
9679         GL_Color(1, 1, 1, 1);
9680 }
9681
9682 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9683 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9684 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9685 {
9686         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9687                 return;
9688         if (prepass)
9689         {
9690                 // render screenspace normalmap to texture
9691                 GL_DepthMask(true);
9692                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9693                 RSurf_DrawBatch();
9694         }
9695
9696         // bind lightmap texture
9697
9698         // water/refraction/reflection/camera surfaces have to be handled specially
9699         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9700         {
9701                 int start, end, startplaneindex;
9702                 for (start = 0;start < texturenumsurfaces;start = end)
9703                 {
9704                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9705                         if(startplaneindex < 0)
9706                         {
9707                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9708                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9709                                 end = start + 1;
9710                                 continue;
9711                         }
9712                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9713                                 ;
9714                         // now that we have a batch using the same planeindex, render it
9715                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9716                         {
9717                                 // render water or distortion background
9718                                 GL_DepthMask(true);
9719                                 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);
9720                                 RSurf_DrawBatch();
9721                                 // blend surface on top
9722                                 GL_DepthMask(false);
9723                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9724                                 RSurf_DrawBatch();
9725                         }
9726                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9727                         {
9728                                 // render surface with reflection texture as input
9729                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9730                                 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);
9731                                 RSurf_DrawBatch();
9732                         }
9733                 }
9734                 return;
9735         }
9736
9737         // render surface batch normally
9738         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9739         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);
9740         RSurf_DrawBatch();
9741 }
9742
9743 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9744 {
9745         // OpenGL 1.3 path - anything not completely ancient
9746         qboolean applycolor;
9747         qboolean applyfog;
9748         int layerindex;
9749         const texturelayer_t *layer;
9750         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);
9751         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9752
9753         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9754         {
9755                 vec4_t layercolor;
9756                 int layertexrgbscale;
9757                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9758                 {
9759                         if (layerindex == 0)
9760                                 GL_AlphaTest(true);
9761                         else
9762                         {
9763                                 GL_AlphaTest(false);
9764                                 GL_DepthFunc(GL_EQUAL);
9765                         }
9766                 }
9767                 GL_DepthMask(layer->depthmask && writedepth);
9768                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9769                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9770                 {
9771                         layertexrgbscale = 4;
9772                         VectorScale(layer->color, 0.25f, layercolor);
9773                 }
9774                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9775                 {
9776                         layertexrgbscale = 2;
9777                         VectorScale(layer->color, 0.5f, layercolor);
9778                 }
9779                 else
9780                 {
9781                         layertexrgbscale = 1;
9782                         VectorScale(layer->color, 1.0f, layercolor);
9783                 }
9784                 layercolor[3] = layer->color[3];
9785                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9786                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9787                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9788                 switch (layer->type)
9789                 {
9790                 case TEXTURELAYERTYPE_LITTEXTURE:
9791                         // single-pass lightmapped texture with 2x rgbscale
9792                         R_Mesh_TexBind(0, r_texture_white);
9793                         R_Mesh_TexMatrix(0, NULL);
9794                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9795                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9796                         R_Mesh_TexBind(1, layer->texture);
9797                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9798                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9799                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9800                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9801                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9802                         else if (FAKELIGHT_ENABLED)
9803                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9804                         else if (rsurface.uselightmaptexture)
9805                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9806                         else
9807                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9808                         break;
9809                 case TEXTURELAYERTYPE_TEXTURE:
9810                         // singletexture unlit texture with transparency support
9811                         R_Mesh_TexBind(0, layer->texture);
9812                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9813                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9814                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9815                         R_Mesh_TexBind(1, 0);
9816                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9817                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9818                         break;
9819                 case TEXTURELAYERTYPE_FOG:
9820                         // singletexture fogging
9821                         if (layer->texture)
9822                         {
9823                                 R_Mesh_TexBind(0, layer->texture);
9824                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9825                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9826                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9827                         }
9828                         else
9829                         {
9830                                 R_Mesh_TexBind(0, 0);
9831                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9832                         }
9833                         R_Mesh_TexBind(1, 0);
9834                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9835                         // generate a color array for the fog pass
9836                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9837                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9838                         RSurf_DrawBatch();
9839                         break;
9840                 default:
9841                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9842                 }
9843         }
9844         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9845         {
9846                 GL_DepthFunc(GL_LEQUAL);
9847                 GL_AlphaTest(false);
9848         }
9849 }
9850
9851 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9852 {
9853         // OpenGL 1.1 - crusty old voodoo path
9854         qboolean applyfog;
9855         int layerindex;
9856         const texturelayer_t *layer;
9857         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);
9858         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9859
9860         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9861         {
9862                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9863                 {
9864                         if (layerindex == 0)
9865                                 GL_AlphaTest(true);
9866                         else
9867                         {
9868                                 GL_AlphaTest(false);
9869                                 GL_DepthFunc(GL_EQUAL);
9870                         }
9871                 }
9872                 GL_DepthMask(layer->depthmask && writedepth);
9873                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9874                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9875                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9876                 switch (layer->type)
9877                 {
9878                 case TEXTURELAYERTYPE_LITTEXTURE:
9879                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9880                         {
9881                                 // two-pass lit texture with 2x rgbscale
9882                                 // first the lightmap pass
9883                                 R_Mesh_TexBind(0, r_texture_white);
9884                                 R_Mesh_TexMatrix(0, NULL);
9885                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9886                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9887                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9888                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9889                                 else if (FAKELIGHT_ENABLED)
9890                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9891                                 else if (rsurface.uselightmaptexture)
9892                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9893                                 else
9894                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9895                                 // then apply the texture to it
9896                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9897                                 R_Mesh_TexBind(0, layer->texture);
9898                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9899                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9900                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9901                                 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);
9902                         }
9903                         else
9904                         {
9905                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9906                                 R_Mesh_TexBind(0, layer->texture);
9907                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9908                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9909                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9910                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9911                                         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);
9912                                 else
9913                                         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);
9914                         }
9915                         break;
9916                 case TEXTURELAYERTYPE_TEXTURE:
9917                         // singletexture unlit texture with transparency support
9918                         R_Mesh_TexBind(0, layer->texture);
9919                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9920                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9921                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9922                         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);
9923                         break;
9924                 case TEXTURELAYERTYPE_FOG:
9925                         // singletexture fogging
9926                         if (layer->texture)
9927                         {
9928                                 R_Mesh_TexBind(0, layer->texture);
9929                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9930                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9931                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9932                         }
9933                         else
9934                         {
9935                                 R_Mesh_TexBind(0, 0);
9936                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9937                         }
9938                         // generate a color array for the fog pass
9939                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9940                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9941                         RSurf_DrawBatch();
9942                         break;
9943                 default:
9944                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9945                 }
9946         }
9947         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9948         {
9949                 GL_DepthFunc(GL_LEQUAL);
9950                 GL_AlphaTest(false);
9951         }
9952 }
9953
9954 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9955 {
9956         int vi;
9957         int j;
9958         r_vertexgeneric_t *batchvertex;
9959         float c[4];
9960
9961 //      R_Mesh_ResetTextureState();
9962         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9963
9964         if(rsurface.texture && rsurface.texture->currentskinframe)
9965         {
9966                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9967                 c[3] *= rsurface.texture->currentalpha;
9968         }
9969         else
9970         {
9971                 c[0] = 1;
9972                 c[1] = 0;
9973                 c[2] = 1;
9974                 c[3] = 1;
9975         }
9976
9977         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9978         {
9979                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9980                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9981                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9982         }
9983
9984         // brighten it up (as texture value 127 means "unlit")
9985         c[0] *= 2 * r_refdef.view.colorscale;
9986         c[1] *= 2 * r_refdef.view.colorscale;
9987         c[2] *= 2 * r_refdef.view.colorscale;
9988
9989         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9990                 c[3] *= r_wateralpha.value;
9991
9992         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9993         {
9994                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9995                 GL_DepthMask(false);
9996         }
9997         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9998         {
9999                 GL_BlendFunc(GL_ONE, GL_ONE);
10000                 GL_DepthMask(false);
10001         }
10002         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10003         {
10004                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10005                 GL_DepthMask(false);
10006         }
10007         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10008         {
10009                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10010                 GL_DepthMask(false);
10011         }
10012         else
10013         {
10014                 GL_BlendFunc(GL_ONE, GL_ZERO);
10015                 GL_DepthMask(writedepth);
10016         }
10017
10018         if (r_showsurfaces.integer == 3)
10019         {
10020                 rsurface.passcolor4f = NULL;
10021
10022                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10023                 {
10024                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10025
10026                         rsurface.passcolor4f = NULL;
10027                         rsurface.passcolor4f_vertexbuffer = 0;
10028                         rsurface.passcolor4f_bufferoffset = 0;
10029                 }
10030                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10031                 {
10032                         qboolean applycolor = true;
10033                         float one = 1.0;
10034
10035                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10036
10037                         r_refdef.lightmapintensity = 1;
10038                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10039                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10040                 }
10041                 else if (FAKELIGHT_ENABLED)
10042                 {
10043                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10044
10045                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10046                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10047                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10048                 }
10049                 else
10050                 {
10051                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10052
10053                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10054                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10055                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10056                 }
10057
10058                 if(!rsurface.passcolor4f)
10059                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10060
10061                 RSurf_DrawBatch_GL11_ApplyAmbient();
10062                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10063                 if(r_refdef.fogenabled)
10064                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10065                 RSurf_DrawBatch_GL11_ClampColor();
10066
10067                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10068                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10069                 RSurf_DrawBatch();
10070         }
10071         else if (!r_refdef.view.showdebug)
10072         {
10073                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10074                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10075                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10076                 {
10077                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10078                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10079                 }
10080                 R_Mesh_PrepareVertices_Generic_Unlock();
10081                 RSurf_DrawBatch();
10082         }
10083         else if (r_showsurfaces.integer == 4)
10084         {
10085                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10086                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10087                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10088                 {
10089                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10090                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10091                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10092                 }
10093                 R_Mesh_PrepareVertices_Generic_Unlock();
10094                 RSurf_DrawBatch();
10095         }
10096         else if (r_showsurfaces.integer == 2)
10097         {
10098                 const int *e;
10099                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10100                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10101                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10102                 {
10103                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10104                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10105                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10106                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10107                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10108                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10109                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10110                 }
10111                 R_Mesh_PrepareVertices_Generic_Unlock();
10112                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10113         }
10114         else
10115         {
10116                 int texturesurfaceindex;
10117                 int k;
10118                 const msurface_t *surface;
10119                 float surfacecolor4f[4];
10120                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10121                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10122                 vi = 0;
10123                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10124                 {
10125                         surface = texturesurfacelist[texturesurfaceindex];
10126                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10127                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10128                         for (j = 0;j < surface->num_vertices;j++)
10129                         {
10130                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10131                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10132                                 vi++;
10133                         }
10134                 }
10135                 R_Mesh_PrepareVertices_Generic_Unlock();
10136                 RSurf_DrawBatch();
10137         }
10138 }
10139
10140 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10141 {
10142         CHECKGLERROR
10143         RSurf_SetupDepthAndCulling();
10144         if (r_showsurfaces.integer)
10145         {
10146                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10147                 return;
10148         }
10149         switch (vid.renderpath)
10150         {
10151         case RENDERPATH_GL20:
10152         case RENDERPATH_D3D9:
10153         case RENDERPATH_D3D10:
10154         case RENDERPATH_D3D11:
10155         case RENDERPATH_SOFT:
10156         case RENDERPATH_GLES2:
10157                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10158                 break;
10159         case RENDERPATH_GL13:
10160         case RENDERPATH_GLES1:
10161                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10162                 break;
10163         case RENDERPATH_GL11:
10164                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10165                 break;
10166         }
10167         CHECKGLERROR
10168 }
10169
10170 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10171 {
10172         CHECKGLERROR
10173         RSurf_SetupDepthAndCulling();
10174         if (r_showsurfaces.integer)
10175         {
10176                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10177                 return;
10178         }
10179         switch (vid.renderpath)
10180         {
10181         case RENDERPATH_GL20:
10182         case RENDERPATH_D3D9:
10183         case RENDERPATH_D3D10:
10184         case RENDERPATH_D3D11:
10185         case RENDERPATH_SOFT:
10186         case RENDERPATH_GLES2:
10187                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10188                 break;
10189         case RENDERPATH_GL13:
10190         case RENDERPATH_GLES1:
10191                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10192                 break;
10193         case RENDERPATH_GL11:
10194                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10195                 break;
10196         }
10197         CHECKGLERROR
10198 }
10199
10200 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10201 {
10202         int i, j;
10203         int texturenumsurfaces, endsurface;
10204         texture_t *texture;
10205         const msurface_t *surface;
10206         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10207
10208         // if the model is static it doesn't matter what value we give for
10209         // wantnormals and wanttangents, so this logic uses only rules applicable
10210         // to a model, knowing that they are meaningless otherwise
10211         if (ent == r_refdef.scene.worldentity)
10212                 RSurf_ActiveWorldEntity();
10213         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10214                 RSurf_ActiveModelEntity(ent, false, false, false);
10215         else
10216         {
10217                 switch (vid.renderpath)
10218                 {
10219                 case RENDERPATH_GL20:
10220                 case RENDERPATH_D3D9:
10221                 case RENDERPATH_D3D10:
10222                 case RENDERPATH_D3D11:
10223                 case RENDERPATH_SOFT:
10224                 case RENDERPATH_GLES2:
10225                         RSurf_ActiveModelEntity(ent, true, true, false);
10226                         break;
10227                 case RENDERPATH_GL11:
10228                 case RENDERPATH_GL13:
10229                 case RENDERPATH_GLES1:
10230                         RSurf_ActiveModelEntity(ent, true, false, false);
10231                         break;
10232                 }
10233         }
10234
10235         if (r_transparentdepthmasking.integer)
10236         {
10237                 qboolean setup = false;
10238                 for (i = 0;i < numsurfaces;i = j)
10239                 {
10240                         j = i + 1;
10241                         surface = rsurface.modelsurfaces + surfacelist[i];
10242                         texture = surface->texture;
10243                         rsurface.texture = R_GetCurrentTexture(texture);
10244                         rsurface.lightmaptexture = NULL;
10245                         rsurface.deluxemaptexture = NULL;
10246                         rsurface.uselightmaptexture = false;
10247                         // scan ahead until we find a different texture
10248                         endsurface = min(i + 1024, numsurfaces);
10249                         texturenumsurfaces = 0;
10250                         texturesurfacelist[texturenumsurfaces++] = surface;
10251                         for (;j < endsurface;j++)
10252                         {
10253                                 surface = rsurface.modelsurfaces + surfacelist[j];
10254                                 if (texture != surface->texture)
10255                                         break;
10256                                 texturesurfacelist[texturenumsurfaces++] = surface;
10257                         }
10258                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10259                                 continue;
10260                         // render the range of surfaces as depth
10261                         if (!setup)
10262                         {
10263                                 setup = true;
10264                                 GL_ColorMask(0,0,0,0);
10265                                 GL_Color(1,1,1,1);
10266                                 GL_DepthTest(true);
10267                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10268                                 GL_DepthMask(true);
10269 //                              R_Mesh_ResetTextureState();
10270                                 R_SetupShader_DepthOrShadow(false);
10271                         }
10272                         RSurf_SetupDepthAndCulling();
10273                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10274                         if (rsurface.batchvertex3fbuffer)
10275                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10276                         else
10277                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10278                         RSurf_DrawBatch();
10279                 }
10280                 if (setup)
10281                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10282         }
10283
10284         for (i = 0;i < numsurfaces;i = j)
10285         {
10286                 j = i + 1;
10287                 surface = rsurface.modelsurfaces + surfacelist[i];
10288                 texture = surface->texture;
10289                 rsurface.texture = R_GetCurrentTexture(texture);
10290                 // scan ahead until we find a different texture
10291                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10292                 texturenumsurfaces = 0;
10293                 texturesurfacelist[texturenumsurfaces++] = surface;
10294                 if(FAKELIGHT_ENABLED)
10295                 {
10296                         rsurface.lightmaptexture = NULL;
10297                         rsurface.deluxemaptexture = NULL;
10298                         rsurface.uselightmaptexture = false;
10299                         for (;j < endsurface;j++)
10300                         {
10301                                 surface = rsurface.modelsurfaces + surfacelist[j];
10302                                 if (texture != surface->texture)
10303                                         break;
10304                                 texturesurfacelist[texturenumsurfaces++] = surface;
10305                         }
10306                 }
10307                 else
10308                 {
10309                         rsurface.lightmaptexture = surface->lightmaptexture;
10310                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10311                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10312                         for (;j < endsurface;j++)
10313                         {
10314                                 surface = rsurface.modelsurfaces + surfacelist[j];
10315                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10316                                         break;
10317                                 texturesurfacelist[texturenumsurfaces++] = surface;
10318                         }
10319                 }
10320                 // render the range of surfaces
10321                 if (ent == r_refdef.scene.worldentity)
10322                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10323                 else
10324                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10325         }
10326         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10327 }
10328
10329 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10330 {
10331         // transparent surfaces get pushed off into the transparent queue
10332         int surfacelistindex;
10333         const msurface_t *surface;
10334         vec3_t tempcenter, center;
10335         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10336         {
10337                 surface = texturesurfacelist[surfacelistindex];
10338                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10339                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10340                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10341                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10342                 if (queueentity->transparent_offset) // transparent offset
10343                 {
10344                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10345                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10346                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10347                 }
10348                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10349         }
10350 }
10351
10352 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10353 {
10354         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10355                 return;
10356         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10357                 return;
10358         RSurf_SetupDepthAndCulling();
10359         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10360         if (rsurface.batchvertex3fbuffer)
10361                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10362         else
10363                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10364         RSurf_DrawBatch();
10365 }
10366
10367 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10368 {
10369         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10370         CHECKGLERROR
10371         if (depthonly)
10372                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10373         else if (prepass)
10374         {
10375                 if (!rsurface.texture->currentnumlayers)
10376                         return;
10377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10378                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10379                 else
10380                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10381         }
10382         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10383                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10384         else if (!rsurface.texture->currentnumlayers)
10385                 return;
10386         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10387         {
10388                 // in the deferred case, transparent surfaces were queued during prepass
10389                 if (!r_shadow_usingdeferredprepass)
10390                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10391         }
10392         else
10393         {
10394                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10395                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10396         }
10397         CHECKGLERROR
10398 }
10399
10400 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10401 {
10402         int i, j;
10403         texture_t *texture;
10404         R_FrameData_SetMark();
10405         // break the surface list down into batches by texture and use of lightmapping
10406         for (i = 0;i < numsurfaces;i = j)
10407         {
10408                 j = i + 1;
10409                 // texture is the base texture pointer, rsurface.texture is the
10410                 // current frame/skin the texture is directing us to use (for example
10411                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10412                 // use skin 1 instead)
10413                 texture = surfacelist[i]->texture;
10414                 rsurface.texture = R_GetCurrentTexture(texture);
10415                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10416                 {
10417                         // if this texture is not the kind we want, skip ahead to the next one
10418                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10419                                 ;
10420                         continue;
10421                 }
10422                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10423                 {
10424                         rsurface.lightmaptexture = NULL;
10425                         rsurface.deluxemaptexture = NULL;
10426                         rsurface.uselightmaptexture = false;
10427                         // simply scan ahead until we find a different texture or lightmap state
10428                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10429                                 ;
10430                 }
10431                 else
10432                 {
10433                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10434                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10435                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10436                         // simply scan ahead until we find a different texture or lightmap state
10437                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10438                                 ;
10439                 }
10440                 // render the range of surfaces
10441                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10442         }
10443         R_FrameData_ReturnToMark();
10444 }
10445
10446 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10447 {
10448         CHECKGLERROR
10449         if (depthonly)
10450                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10451         else if (prepass)
10452         {
10453                 if (!rsurface.texture->currentnumlayers)
10454                         return;
10455                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10456                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10457                 else
10458                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10459         }
10460         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10461                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10462         else if (!rsurface.texture->currentnumlayers)
10463                 return;
10464         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10465         {
10466                 // in the deferred case, transparent surfaces were queued during prepass
10467                 if (!r_shadow_usingdeferredprepass)
10468                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10469         }
10470         else
10471         {
10472                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10473                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10474         }
10475         CHECKGLERROR
10476 }
10477
10478 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10479 {
10480         int i, j;
10481         texture_t *texture;
10482         R_FrameData_SetMark();
10483         // break the surface list down into batches by texture and use of lightmapping
10484         for (i = 0;i < numsurfaces;i = j)
10485         {
10486                 j = i + 1;
10487                 // texture is the base texture pointer, rsurface.texture is the
10488                 // current frame/skin the texture is directing us to use (for example
10489                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10490                 // use skin 1 instead)
10491                 texture = surfacelist[i]->texture;
10492                 rsurface.texture = R_GetCurrentTexture(texture);
10493                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10494                 {
10495                         // if this texture is not the kind we want, skip ahead to the next one
10496                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10497                                 ;
10498                         continue;
10499                 }
10500                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10501                 {
10502                         rsurface.lightmaptexture = NULL;
10503                         rsurface.deluxemaptexture = NULL;
10504                         rsurface.uselightmaptexture = false;
10505                         // simply scan ahead until we find a different texture or lightmap state
10506                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10507                                 ;
10508                 }
10509                 else
10510                 {
10511                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10512                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10513                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10514                         // simply scan ahead until we find a different texture or lightmap state
10515                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10516                                 ;
10517                 }
10518                 // render the range of surfaces
10519                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10520         }
10521         R_FrameData_ReturnToMark();
10522 }
10523
10524 float locboxvertex3f[6*4*3] =
10525 {
10526         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10527         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10528         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10529         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10530         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10531         1,0,0, 0,0,0, 0,1,0, 1,1,0
10532 };
10533
10534 unsigned short locboxelements[6*2*3] =
10535 {
10536          0, 1, 2, 0, 2, 3,
10537          4, 5, 6, 4, 6, 7,
10538          8, 9,10, 8,10,11,
10539         12,13,14, 12,14,15,
10540         16,17,18, 16,18,19,
10541         20,21,22, 20,22,23
10542 };
10543
10544 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10545 {
10546         int i, j;
10547         cl_locnode_t *loc = (cl_locnode_t *)ent;
10548         vec3_t mins, size;
10549         float vertex3f[6*4*3];
10550         CHECKGLERROR
10551         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10552         GL_DepthMask(false);
10553         GL_DepthRange(0, 1);
10554         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10555         GL_DepthTest(true);
10556         GL_CullFace(GL_NONE);
10557         R_EntityMatrix(&identitymatrix);
10558
10559 //      R_Mesh_ResetTextureState();
10560
10561         i = surfacelist[0];
10562         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10563                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10564                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10565                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10566
10567         if (VectorCompare(loc->mins, loc->maxs))
10568         {
10569                 VectorSet(size, 2, 2, 2);
10570                 VectorMA(loc->mins, -0.5f, size, mins);
10571         }
10572         else
10573         {
10574                 VectorCopy(loc->mins, mins);
10575                 VectorSubtract(loc->maxs, loc->mins, size);
10576         }
10577
10578         for (i = 0;i < 6*4*3;)
10579                 for (j = 0;j < 3;j++, i++)
10580                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10581
10582         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10583         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10584         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10585 }
10586
10587 void R_DrawLocs(void)
10588 {
10589         int index;
10590         cl_locnode_t *loc, *nearestloc;
10591         vec3_t center;
10592         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10593         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10594         {
10595                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10596                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10597         }
10598 }
10599
10600 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10601 {
10602         if (decalsystem->decals)
10603                 Mem_Free(decalsystem->decals);
10604         memset(decalsystem, 0, sizeof(*decalsystem));
10605 }
10606
10607 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)
10608 {
10609         tridecal_t *decal;
10610         tridecal_t *decals;
10611         int i;
10612
10613         // expand or initialize the system
10614         if (decalsystem->maxdecals <= decalsystem->numdecals)
10615         {
10616                 decalsystem_t old = *decalsystem;
10617                 qboolean useshortelements;
10618                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10619                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10620                 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)));
10621                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10622                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10623                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10624                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10625                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10626                 if (decalsystem->numdecals)
10627                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10628                 if (old.decals)
10629                         Mem_Free(old.decals);
10630                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10631                         decalsystem->element3i[i] = i;
10632                 if (useshortelements)
10633                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10634                                 decalsystem->element3s[i] = i;
10635         }
10636
10637         // grab a decal and search for another free slot for the next one
10638         decals = decalsystem->decals;
10639         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10640         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10641                 ;
10642         decalsystem->freedecal = i;
10643         if (decalsystem->numdecals <= i)
10644                 decalsystem->numdecals = i + 1;
10645
10646         // initialize the decal
10647         decal->lived = 0;
10648         decal->triangleindex = triangleindex;
10649         decal->surfaceindex = surfaceindex;
10650         decal->decalsequence = decalsequence;
10651         decal->color4f[0][0] = c0[0];
10652         decal->color4f[0][1] = c0[1];
10653         decal->color4f[0][2] = c0[2];
10654         decal->color4f[0][3] = 1;
10655         decal->color4f[1][0] = c1[0];
10656         decal->color4f[1][1] = c1[1];
10657         decal->color4f[1][2] = c1[2];
10658         decal->color4f[1][3] = 1;
10659         decal->color4f[2][0] = c2[0];
10660         decal->color4f[2][1] = c2[1];
10661         decal->color4f[2][2] = c2[2];
10662         decal->color4f[2][3] = 1;
10663         decal->vertex3f[0][0] = v0[0];
10664         decal->vertex3f[0][1] = v0[1];
10665         decal->vertex3f[0][2] = v0[2];
10666         decal->vertex3f[1][0] = v1[0];
10667         decal->vertex3f[1][1] = v1[1];
10668         decal->vertex3f[1][2] = v1[2];
10669         decal->vertex3f[2][0] = v2[0];
10670         decal->vertex3f[2][1] = v2[1];
10671         decal->vertex3f[2][2] = v2[2];
10672         decal->texcoord2f[0][0] = t0[0];
10673         decal->texcoord2f[0][1] = t0[1];
10674         decal->texcoord2f[1][0] = t1[0];
10675         decal->texcoord2f[1][1] = t1[1];
10676         decal->texcoord2f[2][0] = t2[0];
10677         decal->texcoord2f[2][1] = t2[1];
10678         TriangleNormal(v0, v1, v2, decal->plane);
10679         VectorNormalize(decal->plane);
10680         decal->plane[3] = DotProduct(v0, decal->plane);
10681 }
10682
10683 extern cvar_t cl_decals_bias;
10684 extern cvar_t cl_decals_models;
10685 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10686 // baseparms, parms, temps
10687 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)
10688 {
10689         int cornerindex;
10690         int index;
10691         float v[9][3];
10692         const float *vertex3f;
10693         const float *normal3f;
10694         int numpoints;
10695         float points[2][9][3];
10696         float temp[3];
10697         float tc[9][2];
10698         float f;
10699         float c[9][4];
10700         const int *e;
10701
10702         e = rsurface.modelelement3i + 3*triangleindex;
10703
10704         vertex3f = rsurface.modelvertex3f;
10705         normal3f = rsurface.modelnormal3f;
10706
10707         if (normal3f)
10708         {
10709                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10710                 {
10711                         index = 3*e[cornerindex];
10712                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10713                 }
10714         }
10715         else
10716         {
10717                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10718                 {
10719                         index = 3*e[cornerindex];
10720                         VectorCopy(vertex3f + index, v[cornerindex]);
10721                 }
10722         }
10723
10724         // cull backfaces
10725         //TriangleNormal(v[0], v[1], v[2], normal);
10726         //if (DotProduct(normal, localnormal) < 0.0f)
10727         //      continue;
10728         // clip by each of the box planes formed from the projection matrix
10729         // if anything survives, we emit the decal
10730         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]);
10731         if (numpoints < 3)
10732                 return;
10733         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]);
10734         if (numpoints < 3)
10735                 return;
10736         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]);
10737         if (numpoints < 3)
10738                 return;
10739         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]);
10740         if (numpoints < 3)
10741                 return;
10742         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]);
10743         if (numpoints < 3)
10744                 return;
10745         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]);
10746         if (numpoints < 3)
10747                 return;
10748         // some part of the triangle survived, so we have to accept it...
10749         if (dynamic)
10750         {
10751                 // dynamic always uses the original triangle
10752                 numpoints = 3;
10753                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10754                 {
10755                         index = 3*e[cornerindex];
10756                         VectorCopy(vertex3f + index, v[cornerindex]);
10757                 }
10758         }
10759         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10760         {
10761                 // convert vertex positions to texcoords
10762                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10763                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10764                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10765                 // calculate distance fade from the projection origin
10766                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10767                 f = bound(0.0f, f, 1.0f);
10768                 c[cornerindex][0] = r * f;
10769                 c[cornerindex][1] = g * f;
10770                 c[cornerindex][2] = b * f;
10771                 c[cornerindex][3] = 1.0f;
10772                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10773         }
10774         if (dynamic)
10775                 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);
10776         else
10777                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10778                         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);
10779 }
10780 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)
10781 {
10782         matrix4x4_t projection;
10783         decalsystem_t *decalsystem;
10784         qboolean dynamic;
10785         dp_model_t *model;
10786         const msurface_t *surface;
10787         const msurface_t *surfaces;
10788         const int *surfacelist;
10789         const texture_t *texture;
10790         int numtriangles;
10791         int numsurfacelist;
10792         int surfacelistindex;
10793         int surfaceindex;
10794         int triangleindex;
10795         float localorigin[3];
10796         float localnormal[3];
10797         float localmins[3];
10798         float localmaxs[3];
10799         float localsize;
10800         //float normal[3];
10801         float planes[6][4];
10802         float angles[3];
10803         bih_t *bih;
10804         int bih_triangles_count;
10805         int bih_triangles[256];
10806         int bih_surfaces[256];
10807
10808         decalsystem = &ent->decalsystem;
10809         model = ent->model;
10810         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10811         {
10812                 R_DecalSystem_Reset(&ent->decalsystem);
10813                 return;
10814         }
10815
10816         if (!model->brush.data_leafs && !cl_decals_models.integer)
10817         {
10818                 if (decalsystem->model)
10819                         R_DecalSystem_Reset(decalsystem);
10820                 return;
10821         }
10822
10823         if (decalsystem->model != model)
10824                 R_DecalSystem_Reset(decalsystem);
10825         decalsystem->model = model;
10826
10827         RSurf_ActiveModelEntity(ent, true, false, false);
10828
10829         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10830         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10831         VectorNormalize(localnormal);
10832         localsize = worldsize*rsurface.inversematrixscale;
10833         localmins[0] = localorigin[0] - localsize;
10834         localmins[1] = localorigin[1] - localsize;
10835         localmins[2] = localorigin[2] - localsize;
10836         localmaxs[0] = localorigin[0] + localsize;
10837         localmaxs[1] = localorigin[1] + localsize;
10838         localmaxs[2] = localorigin[2] + localsize;
10839
10840         //VectorCopy(localnormal, planes[4]);
10841         //VectorVectors(planes[4], planes[2], planes[0]);
10842         AnglesFromVectors(angles, localnormal, NULL, false);
10843         AngleVectors(angles, planes[0], planes[2], planes[4]);
10844         VectorNegate(planes[0], planes[1]);
10845         VectorNegate(planes[2], planes[3]);
10846         VectorNegate(planes[4], planes[5]);
10847         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10848         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10849         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10850         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10851         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10852         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10853
10854 #if 1
10855 // works
10856 {
10857         matrix4x4_t forwardprojection;
10858         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10859         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10860 }
10861 #else
10862 // broken
10863 {
10864         float projectionvector[4][3];
10865         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10866         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10867         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10868         projectionvector[0][0] = planes[0][0] * ilocalsize;
10869         projectionvector[0][1] = planes[1][0] * ilocalsize;
10870         projectionvector[0][2] = planes[2][0] * ilocalsize;
10871         projectionvector[1][0] = planes[0][1] * ilocalsize;
10872         projectionvector[1][1] = planes[1][1] * ilocalsize;
10873         projectionvector[1][2] = planes[2][1] * ilocalsize;
10874         projectionvector[2][0] = planes[0][2] * ilocalsize;
10875         projectionvector[2][1] = planes[1][2] * ilocalsize;
10876         projectionvector[2][2] = planes[2][2] * ilocalsize;
10877         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10878         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10879         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10880         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10881 }
10882 #endif
10883
10884         dynamic = model->surfmesh.isanimated;
10885         numsurfacelist = model->nummodelsurfaces;
10886         surfacelist = model->sortedmodelsurfaces;
10887         surfaces = model->data_surfaces;
10888
10889         bih = NULL;
10890         bih_triangles_count = -1;
10891         if(!dynamic)
10892         {
10893                 if(model->render_bih.numleafs)
10894                         bih = &model->render_bih;
10895                 else if(model->collision_bih.numleafs)
10896                         bih = &model->collision_bih;
10897         }
10898         if(bih)
10899                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10900         if(bih_triangles_count == 0)
10901                 return;
10902         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10903                 return;
10904         if(bih_triangles_count > 0)
10905         {
10906                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10907                 {
10908                         surfaceindex = bih_surfaces[triangleindex];
10909                         surface = surfaces + surfaceindex;
10910                         texture = surface->texture;
10911                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10912                                 continue;
10913                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10914                                 continue;
10915                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10916                 }
10917         }
10918         else
10919         {
10920                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10921                 {
10922                         surfaceindex = surfacelist[surfacelistindex];
10923                         surface = surfaces + surfaceindex;
10924                         // check cull box first because it rejects more than any other check
10925                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10926                                 continue;
10927                         // skip transparent surfaces
10928                         texture = surface->texture;
10929                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10930                                 continue;
10931                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10932                                 continue;
10933                         numtriangles = surface->num_triangles;
10934                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10935                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10936                 }
10937         }
10938 }
10939
10940 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10941 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)
10942 {
10943         int renderentityindex;
10944         float worldmins[3];
10945         float worldmaxs[3];
10946         entity_render_t *ent;
10947
10948         if (!cl_decals_newsystem.integer)
10949                 return;
10950
10951         worldmins[0] = worldorigin[0] - worldsize;
10952         worldmins[1] = worldorigin[1] - worldsize;
10953         worldmins[2] = worldorigin[2] - worldsize;
10954         worldmaxs[0] = worldorigin[0] + worldsize;
10955         worldmaxs[1] = worldorigin[1] + worldsize;
10956         worldmaxs[2] = worldorigin[2] + worldsize;
10957
10958         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10959
10960         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10961         {
10962                 ent = r_refdef.scene.entities[renderentityindex];
10963                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10964                         continue;
10965
10966                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10967         }
10968 }
10969
10970 typedef struct r_decalsystem_splatqueue_s
10971 {
10972         vec3_t worldorigin;
10973         vec3_t worldnormal;
10974         float color[4];
10975         float tcrange[4];
10976         float worldsize;
10977         int decalsequence;
10978 }
10979 r_decalsystem_splatqueue_t;
10980
10981 int r_decalsystem_numqueued = 0;
10982 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10983
10984 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)
10985 {
10986         r_decalsystem_splatqueue_t *queue;
10987
10988         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10989                 return;
10990
10991         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10992         VectorCopy(worldorigin, queue->worldorigin);
10993         VectorCopy(worldnormal, queue->worldnormal);
10994         Vector4Set(queue->color, r, g, b, a);
10995         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10996         queue->worldsize = worldsize;
10997         queue->decalsequence = cl.decalsequence++;
10998 }
10999
11000 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11001 {
11002         int i;
11003         r_decalsystem_splatqueue_t *queue;
11004
11005         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11006                 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);
11007         r_decalsystem_numqueued = 0;
11008 }
11009
11010 extern cvar_t cl_decals_max;
11011 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11012 {
11013         int i;
11014         decalsystem_t *decalsystem = &ent->decalsystem;
11015         int numdecals;
11016         int killsequence;
11017         tridecal_t *decal;
11018         float frametime;
11019         float lifetime;
11020
11021         if (!decalsystem->numdecals)
11022                 return;
11023
11024         if (r_showsurfaces.integer)
11025                 return;
11026
11027         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11028         {
11029                 R_DecalSystem_Reset(decalsystem);
11030                 return;
11031         }
11032
11033         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11034         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11035
11036         if (decalsystem->lastupdatetime)
11037                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11038         else
11039                 frametime = 0;
11040         decalsystem->lastupdatetime = r_refdef.scene.time;
11041         decal = decalsystem->decals;
11042         numdecals = decalsystem->numdecals;
11043
11044         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11045         {
11046                 if (decal->color4f[0][3])
11047                 {
11048                         decal->lived += frametime;
11049                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11050                         {
11051                                 memset(decal, 0, sizeof(*decal));
11052                                 if (decalsystem->freedecal > i)
11053                                         decalsystem->freedecal = i;
11054                         }
11055                 }
11056         }
11057         decal = decalsystem->decals;
11058         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11059                 numdecals--;
11060
11061         // collapse the array by shuffling the tail decals into the gaps
11062         for (;;)
11063         {
11064                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11065                         decalsystem->freedecal++;
11066                 if (decalsystem->freedecal == numdecals)
11067                         break;
11068                 decal[decalsystem->freedecal] = decal[--numdecals];
11069         }
11070
11071         decalsystem->numdecals = numdecals;
11072
11073         if (numdecals <= 0)
11074         {
11075                 // if there are no decals left, reset decalsystem
11076                 R_DecalSystem_Reset(decalsystem);
11077         }
11078 }
11079
11080 extern skinframe_t *decalskinframe;
11081 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11082 {
11083         int i;
11084         decalsystem_t *decalsystem = &ent->decalsystem;
11085         int numdecals;
11086         tridecal_t *decal;
11087         float faderate;
11088         float alpha;
11089         float *v3f;
11090         float *c4f;
11091         float *t2f;
11092         const int *e;
11093         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11094         int numtris = 0;
11095
11096         numdecals = decalsystem->numdecals;
11097         if (!numdecals)
11098                 return;
11099
11100         if (r_showsurfaces.integer)
11101                 return;
11102
11103         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11104         {
11105                 R_DecalSystem_Reset(decalsystem);
11106                 return;
11107         }
11108
11109         // if the model is static it doesn't matter what value we give for
11110         // wantnormals and wanttangents, so this logic uses only rules applicable
11111         // to a model, knowing that they are meaningless otherwise
11112         if (ent == r_refdef.scene.worldentity)
11113                 RSurf_ActiveWorldEntity();
11114         else
11115                 RSurf_ActiveModelEntity(ent, false, false, false);
11116
11117         decalsystem->lastupdatetime = r_refdef.scene.time;
11118         decal = decalsystem->decals;
11119
11120         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11121
11122         // update vertex positions for animated models
11123         v3f = decalsystem->vertex3f;
11124         c4f = decalsystem->color4f;
11125         t2f = decalsystem->texcoord2f;
11126         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11127         {
11128                 if (!decal->color4f[0][3])
11129                         continue;
11130
11131                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11132                         continue;
11133
11134                 // skip backfaces
11135                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11136                         continue;
11137
11138                 // update color values for fading decals
11139                 if (decal->lived >= cl_decals_time.value)
11140                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11141                 else
11142                         alpha = 1.0f;
11143
11144                 c4f[ 0] = decal->color4f[0][0] * alpha;
11145                 c4f[ 1] = decal->color4f[0][1] * alpha;
11146                 c4f[ 2] = decal->color4f[0][2] * alpha;
11147                 c4f[ 3] = 1;
11148                 c4f[ 4] = decal->color4f[1][0] * alpha;
11149                 c4f[ 5] = decal->color4f[1][1] * alpha;
11150                 c4f[ 6] = decal->color4f[1][2] * alpha;
11151                 c4f[ 7] = 1;
11152                 c4f[ 8] = decal->color4f[2][0] * alpha;
11153                 c4f[ 9] = decal->color4f[2][1] * alpha;
11154                 c4f[10] = decal->color4f[2][2] * alpha;
11155                 c4f[11] = 1;
11156
11157                 t2f[0] = decal->texcoord2f[0][0];
11158                 t2f[1] = decal->texcoord2f[0][1];
11159                 t2f[2] = decal->texcoord2f[1][0];
11160                 t2f[3] = decal->texcoord2f[1][1];
11161                 t2f[4] = decal->texcoord2f[2][0];
11162                 t2f[5] = decal->texcoord2f[2][1];
11163
11164                 // update vertex positions for animated models
11165                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11166                 {
11167                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11168                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11169                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11170                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11171                 }
11172                 else
11173                 {
11174                         VectorCopy(decal->vertex3f[0], v3f);
11175                         VectorCopy(decal->vertex3f[1], v3f + 3);
11176                         VectorCopy(decal->vertex3f[2], v3f + 6);
11177                 }
11178
11179                 if (r_refdef.fogenabled)
11180                 {
11181                         alpha = RSurf_FogVertex(v3f);
11182                         VectorScale(c4f, alpha, c4f);
11183                         alpha = RSurf_FogVertex(v3f + 3);
11184                         VectorScale(c4f + 4, alpha, c4f + 4);
11185                         alpha = RSurf_FogVertex(v3f + 6);
11186                         VectorScale(c4f + 8, alpha, c4f + 8);
11187                 }
11188
11189                 v3f += 9;
11190                 c4f += 12;
11191                 t2f += 6;
11192                 numtris++;
11193         }
11194
11195         if (numtris > 0)
11196         {
11197                 r_refdef.stats.drawndecals += numtris;
11198
11199                 // now render the decals all at once
11200                 // (this assumes they all use one particle font texture!)
11201                 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);
11202 //              R_Mesh_ResetTextureState();
11203                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11204                 GL_DepthMask(false);
11205                 GL_DepthRange(0, 1);
11206                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11207                 GL_DepthTest(true);
11208                 GL_CullFace(GL_NONE);
11209                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11210                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11211                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11212         }
11213 }
11214
11215 static void R_DrawModelDecals(void)
11216 {
11217         int i, numdecals;
11218
11219         // fade faster when there are too many decals
11220         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11221         for (i = 0;i < r_refdef.scene.numentities;i++)
11222                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11223
11224         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11225         for (i = 0;i < r_refdef.scene.numentities;i++)
11226                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11227                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11228
11229         R_DecalSystem_ApplySplatEntitiesQueue();
11230
11231         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11232         for (i = 0;i < r_refdef.scene.numentities;i++)
11233                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11234
11235         r_refdef.stats.totaldecals += numdecals;
11236
11237         if (r_showsurfaces.integer)
11238                 return;
11239
11240         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11241
11242         for (i = 0;i < r_refdef.scene.numentities;i++)
11243         {
11244                 if (!r_refdef.viewcache.entityvisible[i])
11245                         continue;
11246                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11247                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11248         }
11249 }
11250
11251 extern cvar_t mod_collision_bih;
11252 void R_DrawDebugModel(void)
11253 {
11254         entity_render_t *ent = rsurface.entity;
11255         int i, j, k, l, flagsmask;
11256         const msurface_t *surface;
11257         dp_model_t *model = ent->model;
11258         vec3_t v;
11259
11260         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11261                 return;
11262
11263         if (r_showoverdraw.value > 0)
11264         {
11265                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11266                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11267                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11268                 GL_DepthTest(false);
11269                 GL_DepthMask(false);
11270                 GL_DepthRange(0, 1);
11271                 GL_BlendFunc(GL_ONE, GL_ONE);
11272                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11273                 {
11274                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11275                                 continue;
11276                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11277                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11278                         {
11279                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11280                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11281                                 if (!rsurface.texture->currentlayers->depthmask)
11282                                         GL_Color(c, 0, 0, 1.0f);
11283                                 else if (ent == r_refdef.scene.worldentity)
11284                                         GL_Color(c, c, c, 1.0f);
11285                                 else
11286                                         GL_Color(0, c, 0, 1.0f);
11287                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11288                                 RSurf_DrawBatch();
11289                         }
11290                 }
11291                 rsurface.texture = NULL;
11292         }
11293
11294         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11295
11296 //      R_Mesh_ResetTextureState();
11297         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11298         GL_DepthRange(0, 1);
11299         GL_DepthTest(!r_showdisabledepthtest.integer);
11300         GL_DepthMask(false);
11301         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11302
11303         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11304         {
11305                 int triangleindex;
11306                 int bihleafindex;
11307                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11308                 const q3mbrush_t *brush;
11309                 const bih_t *bih = &model->collision_bih;
11310                 const bih_leaf_t *bihleaf;
11311                 float vertex3f[3][3];
11312                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11313                 cullbox = false;
11314                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11315                 {
11316                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11317                                 continue;
11318                         switch (bihleaf->type)
11319                         {
11320                         case BIH_BRUSH:
11321                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11322                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11323                                 {
11324                                         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);
11325                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11326                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11327                                 }
11328                                 break;
11329                         case BIH_COLLISIONTRIANGLE:
11330                                 triangleindex = bihleaf->itemindex;
11331                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11332                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11333                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11334                                 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);
11335                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11336                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11337                                 break;
11338                         case BIH_RENDERTRIANGLE:
11339                                 triangleindex = bihleaf->itemindex;
11340                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11341                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11342                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11343                                 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);
11344                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11345                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11346                                 break;
11347                         }
11348                 }
11349         }
11350
11351         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11352
11353         if (r_showtris.integer && qglPolygonMode)
11354         {
11355                 if (r_showdisabledepthtest.integer)
11356                 {
11357                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11358                         GL_DepthMask(false);
11359                 }
11360                 else
11361                 {
11362                         GL_BlendFunc(GL_ONE, GL_ZERO);
11363                         GL_DepthMask(true);
11364                 }
11365                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11366                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11367                 {
11368                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11369                                 continue;
11370                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11371                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11372                         {
11373                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11374                                 if (!rsurface.texture->currentlayers->depthmask)
11375                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11376                                 else if (ent == r_refdef.scene.worldentity)
11377                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11378                                 else
11379                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11380                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11381                                 RSurf_DrawBatch();
11382                         }
11383                 }
11384                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11385                 rsurface.texture = NULL;
11386         }
11387
11388         if (r_shownormals.value != 0 && qglBegin)
11389         {
11390                 if (r_showdisabledepthtest.integer)
11391                 {
11392                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11393                         GL_DepthMask(false);
11394                 }
11395                 else
11396                 {
11397                         GL_BlendFunc(GL_ONE, GL_ZERO);
11398                         GL_DepthMask(true);
11399                 }
11400                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11401                 {
11402                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11403                                 continue;
11404                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11405                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11406                         {
11407                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11408                                 qglBegin(GL_LINES);
11409                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11410                                 {
11411                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11412                                         {
11413                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11414                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11415                                                 qglVertex3f(v[0], v[1], v[2]);
11416                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11417                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11418                                                 qglVertex3f(v[0], v[1], v[2]);
11419                                         }
11420                                 }
11421                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11422                                 {
11423                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11424                                         {
11425                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11426                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11427                                                 qglVertex3f(v[0], v[1], v[2]);
11428                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11429                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11430                                                 qglVertex3f(v[0], v[1], v[2]);
11431                                         }
11432                                 }
11433                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11434                                 {
11435                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11436                                         {
11437                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11438                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11439                                                 qglVertex3f(v[0], v[1], v[2]);
11440                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11441                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11442                                                 qglVertex3f(v[0], v[1], v[2]);
11443                                         }
11444                                 }
11445                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11446                                 {
11447                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11448                                         {
11449                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11450                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11451                                                 qglVertex3f(v[0], v[1], v[2]);
11452                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11453                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11454                                                 qglVertex3f(v[0], v[1], v[2]);
11455                                         }
11456                                 }
11457                                 qglEnd();
11458                                 CHECKGLERROR
11459                         }
11460                 }
11461                 rsurface.texture = NULL;
11462         }
11463 }
11464
11465 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11466 int r_maxsurfacelist = 0;
11467 const msurface_t **r_surfacelist = NULL;
11468 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11469 {
11470         int i, j, endj, flagsmask;
11471         dp_model_t *model = r_refdef.scene.worldmodel;
11472         msurface_t *surfaces;
11473         unsigned char *update;
11474         int numsurfacelist = 0;
11475         if (model == NULL)
11476                 return;
11477
11478         if (r_maxsurfacelist < model->num_surfaces)
11479         {
11480                 r_maxsurfacelist = model->num_surfaces;
11481                 if (r_surfacelist)
11482                         Mem_Free((msurface_t**)r_surfacelist);
11483                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11484         }
11485
11486         RSurf_ActiveWorldEntity();
11487
11488         surfaces = model->data_surfaces;
11489         update = model->brushq1.lightmapupdateflags;
11490
11491         // update light styles on this submodel
11492         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11493         {
11494                 model_brush_lightstyleinfo_t *style;
11495                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11496                 {
11497                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11498                         {
11499                                 int *list = style->surfacelist;
11500                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11501                                 for (j = 0;j < style->numsurfaces;j++)
11502                                         update[list[j]] = true;
11503                         }
11504                 }
11505         }
11506
11507         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11508
11509         if (debug)
11510         {
11511                 R_DrawDebugModel();
11512                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11513                 return;
11514         }
11515
11516         rsurface.lightmaptexture = NULL;
11517         rsurface.deluxemaptexture = NULL;
11518         rsurface.uselightmaptexture = false;
11519         rsurface.texture = NULL;
11520         rsurface.rtlight = NULL;
11521         numsurfacelist = 0;
11522         // add visible surfaces to draw list
11523         for (i = 0;i < model->nummodelsurfaces;i++)
11524         {
11525                 j = model->sortedmodelsurfaces[i];
11526                 if (r_refdef.viewcache.world_surfacevisible[j])
11527                         r_surfacelist[numsurfacelist++] = surfaces + j;
11528         }
11529         // update lightmaps if needed
11530         if (model->brushq1.firstrender)
11531         {
11532                 model->brushq1.firstrender = false;
11533                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11534                         if (update[j])
11535                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11536         }
11537         else if (update)
11538         {
11539                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11540                         if (r_refdef.viewcache.world_surfacevisible[j])
11541                                 if (update[j])
11542                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11543         }
11544         // don't do anything if there were no surfaces
11545         if (!numsurfacelist)
11546         {
11547                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11548                 return;
11549         }
11550         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11551
11552         // add to stats if desired
11553         if (r_speeds.integer && !skysurfaces && !depthonly)
11554         {
11555                 r_refdef.stats.world_surfaces += numsurfacelist;
11556                 for (j = 0;j < numsurfacelist;j++)
11557                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11558         }
11559
11560         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11561 }
11562
11563 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11564 {
11565         int i, j, endj, flagsmask;
11566         dp_model_t *model = ent->model;
11567         msurface_t *surfaces;
11568         unsigned char *update;
11569         int numsurfacelist = 0;
11570         if (model == NULL)
11571                 return;
11572
11573         if (r_maxsurfacelist < model->num_surfaces)
11574         {
11575                 r_maxsurfacelist = model->num_surfaces;
11576                 if (r_surfacelist)
11577                         Mem_Free((msurface_t **)r_surfacelist);
11578                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11579         }
11580
11581         // if the model is static it doesn't matter what value we give for
11582         // wantnormals and wanttangents, so this logic uses only rules applicable
11583         // to a model, knowing that they are meaningless otherwise
11584         if (ent == r_refdef.scene.worldentity)
11585                 RSurf_ActiveWorldEntity();
11586         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11587                 RSurf_ActiveModelEntity(ent, false, false, false);
11588         else if (prepass)
11589                 RSurf_ActiveModelEntity(ent, true, true, true);
11590         else if (depthonly)
11591         {
11592                 switch (vid.renderpath)
11593                 {
11594                 case RENDERPATH_GL20:
11595                 case RENDERPATH_D3D9:
11596                 case RENDERPATH_D3D10:
11597                 case RENDERPATH_D3D11:
11598                 case RENDERPATH_SOFT:
11599                 case RENDERPATH_GLES2:
11600                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11601                         break;
11602                 case RENDERPATH_GL11:
11603                 case RENDERPATH_GL13:
11604                 case RENDERPATH_GLES1:
11605                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11606                         break;
11607                 }
11608         }
11609         else
11610         {
11611                 switch (vid.renderpath)
11612                 {
11613                 case RENDERPATH_GL20:
11614                 case RENDERPATH_D3D9:
11615                 case RENDERPATH_D3D10:
11616                 case RENDERPATH_D3D11:
11617                 case RENDERPATH_SOFT:
11618                 case RENDERPATH_GLES2:
11619                         RSurf_ActiveModelEntity(ent, true, true, false);
11620                         break;
11621                 case RENDERPATH_GL11:
11622                 case RENDERPATH_GL13:
11623                 case RENDERPATH_GLES1:
11624                         RSurf_ActiveModelEntity(ent, true, false, false);
11625                         break;
11626                 }
11627         }
11628
11629         surfaces = model->data_surfaces;
11630         update = model->brushq1.lightmapupdateflags;
11631
11632         // update light styles
11633         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11634         {
11635                 model_brush_lightstyleinfo_t *style;
11636                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11637                 {
11638                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11639                         {
11640                                 int *list = style->surfacelist;
11641                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11642                                 for (j = 0;j < style->numsurfaces;j++)
11643                                         update[list[j]] = true;
11644                         }
11645                 }
11646         }
11647
11648         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11649
11650         if (debug)
11651         {
11652                 R_DrawDebugModel();
11653                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11654                 return;
11655         }
11656
11657         rsurface.lightmaptexture = NULL;
11658         rsurface.deluxemaptexture = NULL;
11659         rsurface.uselightmaptexture = false;
11660         rsurface.texture = NULL;
11661         rsurface.rtlight = NULL;
11662         numsurfacelist = 0;
11663         // add visible surfaces to draw list
11664         for (i = 0;i < model->nummodelsurfaces;i++)
11665                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11666         // don't do anything if there were no surfaces
11667         if (!numsurfacelist)
11668         {
11669                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11670                 return;
11671         }
11672         // update lightmaps if needed
11673         if (update)
11674         {
11675                 int updated = 0;
11676                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11677                 {
11678                         if (update[j])
11679                         {
11680                                 updated++;
11681                                 R_BuildLightMap(ent, surfaces + j);
11682                         }
11683                 }
11684         }
11685         if (update)
11686                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11687                         if (update[j])
11688                                 R_BuildLightMap(ent, surfaces + j);
11689         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11690
11691         // add to stats if desired
11692         if (r_speeds.integer && !skysurfaces && !depthonly)
11693         {
11694                 r_refdef.stats.entities_surfaces += numsurfacelist;
11695                 for (j = 0;j < numsurfacelist;j++)
11696                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11697         }
11698
11699         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11700 }
11701
11702 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11703 {
11704         static texture_t texture;
11705         static msurface_t surface;
11706         const msurface_t *surfacelist = &surface;
11707
11708         // fake enough texture and surface state to render this geometry
11709
11710         texture.update_lastrenderframe = -1; // regenerate this texture
11711         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11712         texture.currentskinframe = skinframe;
11713         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11714         texture.offsetmapping = OFFSETMAPPING_OFF;
11715         texture.offsetscale = 1;
11716         texture.specularscalemod = 1;
11717         texture.specularpowermod = 1;
11718
11719         surface.texture = &texture;
11720         surface.num_triangles = numtriangles;
11721         surface.num_firsttriangle = firsttriangle;
11722         surface.num_vertices = numvertices;
11723         surface.num_firstvertex = firstvertex;
11724
11725         // now render it
11726         rsurface.texture = R_GetCurrentTexture(surface.texture);
11727         rsurface.lightmaptexture = NULL;
11728         rsurface.deluxemaptexture = NULL;
11729         rsurface.uselightmaptexture = false;
11730         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11731 }
11732
11733 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)
11734 {
11735         static msurface_t surface;
11736         const msurface_t *surfacelist = &surface;
11737
11738         // fake enough texture and surface state to render this geometry
11739         surface.texture = texture;
11740         surface.num_triangles = numtriangles;
11741         surface.num_firsttriangle = firsttriangle;
11742         surface.num_vertices = numvertices;
11743         surface.num_firstvertex = firstvertex;
11744
11745         // now render it
11746         rsurface.texture = R_GetCurrentTexture(surface.texture);
11747         rsurface.lightmaptexture = NULL;
11748         rsurface.deluxemaptexture = NULL;
11749         rsurface.uselightmaptexture = false;
11750         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11751 }