]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
make sure gloss never calculates 0^0
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141
142 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)"};
143 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"};
144
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 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)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174
175 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)"};
176 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
177 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"};
178 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
179 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
180 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
181 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"};
182
183 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
184 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
185 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
186 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
187
188 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
189 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
190 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
191 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
192 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
193 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
194 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
195
196 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
197 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
198 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
199 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)"};
200 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
201 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
202 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
205 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
206 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
207
208 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"};
209
210 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"};
211
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
218
219 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."};
220
221 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)"};
222
223 extern cvar_t v_glslgamma;
224 extern cvar_t v_glslgamma_2d;
225
226 extern qboolean v_flipped_state;
227
228 static struct r_bloomstate_s
229 {
230         qboolean enabled;
231         qboolean hdr;
232
233         int bloomwidth, bloomheight;
234
235         textype_t texturetype;
236         int viewfbo; // used to check if r_viewfbo cvar has changed
237
238         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241
242         int screentexturewidth, screentextureheight;
243         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244
245         int bloomtexturewidth, bloomtextureheight;
246         rtexture_t *texture_bloom;
247
248         // arrays for rendering the screen passes
249         float screentexcoord2f[8];
250         float bloomtexcoord2f[8];
251         float offsettexcoord2f[8];
252
253         r_viewport_t viewport;
254 }
255 r_bloomstate;
256
257 r_waterstate_t r_waterstate;
258
259 /// shadow volume bsp struct with automatically growing nodes buffer
260 svbsp_t r_svbsp;
261
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
275
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
278 {
279         char basename[64];
280         rtexture_t *texture;
281 }
282 cubemapinfo_t;
283
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
290
291 typedef struct r_qwskincache_s
292 {
293         char name[MAX_QPATH];
294         skinframe_t *skinframe;
295 }
296 r_qwskincache_t;
297
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
300
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
305 {
306         0, 0, 0,
307         1, 0, 0,
308         1, 1, 0,
309         0, 1, 0
310 };
311 const float r_d3dscreenvertex3f[12] =
312 {
313         0, 1, 0,
314         1, 1, 0,
315         1, 0, 0,
316         0, 0, 0
317 };
318
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = in[0] * r;
325                 out[1] = in[1] * g;
326                 out[2] = in[2] * b;
327                 out[3] = in[3];
328                 in += 4;
329                 out += 4;
330         }
331 }
332
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = r;
339                 out[1] = g;
340                 out[2] = b;
341                 out[3] = a;
342                 out += 4;
343         }
344 }
345
346 // FIXME: move this to client?
347 void FOG_clear(void)
348 {
349         if (gamemode == GAME_NEHAHRA)
350         {
351                 Cvar_Set("gl_fogenable", "0");
352                 Cvar_Set("gl_fogdensity", "0.2");
353                 Cvar_Set("gl_fogred", "0.3");
354                 Cvar_Set("gl_foggreen", "0.3");
355                 Cvar_Set("gl_fogblue", "0.3");
356         }
357         r_refdef.fog_density = 0;
358         r_refdef.fog_red = 0;
359         r_refdef.fog_green = 0;
360         r_refdef.fog_blue = 0;
361         r_refdef.fog_alpha = 1;
362         r_refdef.fog_start = 0;
363         r_refdef.fog_end = 16384;
364         r_refdef.fog_height = 1<<30;
365         r_refdef.fog_fadedepth = 128;
366         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 }
368
369 static void R_BuildBlankTextures(void)
370 {
371         unsigned char data[4];
372         data[2] = 128; // normal X
373         data[1] = 128; // normal Y
374         data[0] = 255; // normal Z
375         data[3] = 128; // height
376         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377         data[0] = 255;
378         data[1] = 255;
379         data[2] = 255;
380         data[3] = 255;
381         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 128;
383         data[1] = 128;
384         data[2] = 128;
385         data[3] = 255;
386         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 0;
388         data[1] = 0;
389         data[2] = 0;
390         data[3] = 255;
391         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNoTexture(void)
395 {
396         int x, y;
397         unsigned char pix[16][16][4];
398         // this makes a light grey/dark grey checkerboard texture
399         for (y = 0;y < 16;y++)
400         {
401                 for (x = 0;x < 16;x++)
402                 {
403                         if ((y < 8) ^ (x < 8))
404                         {
405                                 pix[y][x][0] = 128;
406                                 pix[y][x][1] = 128;
407                                 pix[y][x][2] = 128;
408                                 pix[y][x][3] = 255;
409                         }
410                         else
411                         {
412                                 pix[y][x][0] = 64;
413                                 pix[y][x][1] = 64;
414                                 pix[y][x][2] = 64;
415                                 pix[y][x][3] = 255;
416                         }
417                 }
418         }
419         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildWhiteCube(void)
423 {
424         unsigned char data[6*1*1*4];
425         memset(data, 255, sizeof(data));
426         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildNormalizationCube(void)
430 {
431         int x, y, side;
432         vec3_t v;
433         vec_t s, t, intensity;
434 #define NORMSIZE 64
435         unsigned char *data;
436         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437         for (side = 0;side < 6;side++)
438         {
439                 for (y = 0;y < NORMSIZE;y++)
440                 {
441                         for (x = 0;x < NORMSIZE;x++)
442                         {
443                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 switch(side)
446                                 {
447                                 default:
448                                 case 0:
449                                         v[0] = 1;
450                                         v[1] = -t;
451                                         v[2] = -s;
452                                         break;
453                                 case 1:
454                                         v[0] = -1;
455                                         v[1] = -t;
456                                         v[2] = s;
457                                         break;
458                                 case 2:
459                                         v[0] = s;
460                                         v[1] = 1;
461                                         v[2] = t;
462                                         break;
463                                 case 3:
464                                         v[0] = s;
465                                         v[1] = -1;
466                                         v[2] = -t;
467                                         break;
468                                 case 4:
469                                         v[0] = s;
470                                         v[1] = -t;
471                                         v[2] = 1;
472                                         break;
473                                 case 5:
474                                         v[0] = -s;
475                                         v[1] = -t;
476                                         v[2] = -1;
477                                         break;
478                                 }
479                                 intensity = 127.0f / sqrt(DotProduct(v, v));
480                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483                                 data[((side*64+y)*64+x)*4+3] = 255;
484                         }
485                 }
486         }
487         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
488         Mem_Free(data);
489 }
490
491 static void R_BuildFogTexture(void)
492 {
493         int x, b;
494 #define FOGWIDTH 256
495         unsigned char data1[FOGWIDTH][4];
496         //unsigned char data2[FOGWIDTH][4];
497         double d, r, alpha;
498
499         r_refdef.fogmasktable_start = r_refdef.fog_start;
500         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501         r_refdef.fogmasktable_range = r_refdef.fogrange;
502         r_refdef.fogmasktable_density = r_refdef.fog_density;
503
504         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506         {
507                 d = (x * r - r_refdef.fogmasktable_start);
508                 if(developer_extra.integer)
509                         Con_DPrintf("%f ", d);
510                 d = max(0, d);
511                 if (r_fog_exp2.integer)
512                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513                 else
514                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515                 if(developer_extra.integer)
516                         Con_DPrintf(" : %f ", alpha);
517                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518                 if(developer_extra.integer)
519                         Con_DPrintf(" = %f\n", alpha);
520                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521         }
522
523         for (x = 0;x < FOGWIDTH;x++)
524         {
525                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
526                 data1[x][0] = b;
527                 data1[x][1] = b;
528                 data1[x][2] = b;
529                 data1[x][3] = 255;
530                 //data2[x][0] = 255 - b;
531                 //data2[x][1] = 255 - b;
532                 //data2[x][2] = 255 - b;
533                 //data2[x][3] = 255;
534         }
535         if (r_texture_fogattenuation)
536         {
537                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539         }
540         else
541         {
542                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
544         }
545 }
546
547 static void R_BuildFogHeightTexture(void)
548 {
549         unsigned char *inpixels;
550         int size;
551         int x;
552         int y;
553         int j;
554         float c[4];
555         float f;
556         inpixels = NULL;
557         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558         if (r_refdef.fogheighttexturename[0])
559                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560         if (!inpixels)
561         {
562                 r_refdef.fog_height_tablesize = 0;
563                 if (r_texture_fogheighttexture)
564                         R_FreeTexture(r_texture_fogheighttexture);
565                 r_texture_fogheighttexture = NULL;
566                 if (r_refdef.fog_height_table2d)
567                         Mem_Free(r_refdef.fog_height_table2d);
568                 r_refdef.fog_height_table2d = NULL;
569                 if (r_refdef.fog_height_table1d)
570                         Mem_Free(r_refdef.fog_height_table1d);
571                 r_refdef.fog_height_table1d = NULL;
572                 return;
573         }
574         size = image_width;
575         r_refdef.fog_height_tablesize = size;
576         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579         Mem_Free(inpixels);
580         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
581         // average fog color table accounting for every fog layer between a point
582         // and the camera.  (Note: attenuation is handled separately!)
583         for (y = 0;y < size;y++)
584         {
585                 for (x = 0;x < size;x++)
586                 {
587                         Vector4Clear(c);
588                         f = 0;
589                         if (x < y)
590                         {
591                                 for (j = x;j <= y;j++)
592                                 {
593                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594                                         f++;
595                                 }
596                         }
597                         else
598                         {
599                                 for (j = x;j >= y;j--)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         f = 1.0f / f;
606                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610                 }
611         }
612         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 }
614
615 //=======================================================================================================================================================
616
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
619 ;
620
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
623 ;
624
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
627
628 //=======================================================================================================================================================
629
630 typedef struct shaderpermutationinfo_s
631 {
632         const char *pretext;
633         const char *name;
634 }
635 shaderpermutationinfo_t;
636
637 typedef struct shadermodeinfo_s
638 {
639         const char *vertexfilename;
640         const char *geometryfilename;
641         const char *fragmentfilename;
642         const char *pretext;
643         const char *name;
644 }
645 shadermodeinfo_t;
646
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {
650         {"#define USEDIFFUSE\n", " diffuse"},
651         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652         {"#define USEVIEWTINT\n", " viewtint"},
653         {"#define USECOLORMAPPING\n", " colormapping"},
654         {"#define USESATURATION\n", " saturation"},
655         {"#define USEFOGINSIDE\n", " foginside"},
656         {"#define USEFOGOUTSIDE\n", " fogoutside"},
657         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659         {"#define USEGAMMARAMPS\n", " gammaramps"},
660         {"#define USECUBEFILTER\n", " cubefilter"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEBLOOM\n", " bloom"},
663         {"#define USESPECULAR\n", " specular"},
664         {"#define USEPOSTPROCESSING\n", " postprocessing"},
665         {"#define USEREFLECTION\n", " reflection"},
666         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675         {"#define USEALPHAKILL\n", " alphakill"},
676         {"#define USEREFLECTCUBE\n", " reflectcube"},
677         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678         {"#define USEBOUNCEGRID\n", " bouncegrid"},
679         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
680         {"#define USETRIPPY\n", " trippy"},
681 };
682
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 };
727
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
730 {
731         /// hash lookup data
732         struct r_glsl_permutation_s *hashnext;
733         unsigned int mode;
734         unsigned int permutation;
735
736         /// indicates if we have tried compiling this permutation already
737         qboolean compiled;
738         /// 0 if compilation failed
739         int program;
740         // texture units assigned to each detected uniform
741         int tex_Texture_First;
742         int tex_Texture_Second;
743         int tex_Texture_GammaRamps;
744         int tex_Texture_Normal;
745         int tex_Texture_Color;
746         int tex_Texture_Gloss;
747         int tex_Texture_Glow;
748         int tex_Texture_SecondaryNormal;
749         int tex_Texture_SecondaryColor;
750         int tex_Texture_SecondaryGloss;
751         int tex_Texture_SecondaryGlow;
752         int tex_Texture_Pants;
753         int tex_Texture_Shirt;
754         int tex_Texture_FogHeightTexture;
755         int tex_Texture_FogMask;
756         int tex_Texture_Lightmap;
757         int tex_Texture_Deluxemap;
758         int tex_Texture_Attenuation;
759         int tex_Texture_Cube;
760         int tex_Texture_Refraction;
761         int tex_Texture_Reflection;
762         int tex_Texture_ShadowMap2D;
763         int tex_Texture_CubeProjection;
764         int tex_Texture_ScreenDepth;
765         int tex_Texture_ScreenNormalMap;
766         int tex_Texture_ScreenDiffuse;
767         int tex_Texture_ScreenSpecular;
768         int tex_Texture_ReflectMask;
769         int tex_Texture_ReflectCube;
770         int tex_Texture_BounceGrid;
771         /// locations of detected uniforms in program object, or -1 if not found
772         int loc_Texture_First;
773         int loc_Texture_Second;
774         int loc_Texture_GammaRamps;
775         int loc_Texture_Normal;
776         int loc_Texture_Color;
777         int loc_Texture_Gloss;
778         int loc_Texture_Glow;
779         int loc_Texture_SecondaryNormal;
780         int loc_Texture_SecondaryColor;
781         int loc_Texture_SecondaryGloss;
782         int loc_Texture_SecondaryGlow;
783         int loc_Texture_Pants;
784         int loc_Texture_Shirt;
785         int loc_Texture_FogHeightTexture;
786         int loc_Texture_FogMask;
787         int loc_Texture_Lightmap;
788         int loc_Texture_Deluxemap;
789         int loc_Texture_Attenuation;
790         int loc_Texture_Cube;
791         int loc_Texture_Refraction;
792         int loc_Texture_Reflection;
793         int loc_Texture_ShadowMap2D;
794         int loc_Texture_CubeProjection;
795         int loc_Texture_ScreenDepth;
796         int loc_Texture_ScreenNormalMap;
797         int loc_Texture_ScreenDiffuse;
798         int loc_Texture_ScreenSpecular;
799         int loc_Texture_ReflectMask;
800         int loc_Texture_ReflectCube;
801         int loc_Texture_BounceGrid;
802         int loc_Alpha;
803         int loc_BloomBlur_Parameters;
804         int loc_ClientTime;
805         int loc_Color_Ambient;
806         int loc_Color_Diffuse;
807         int loc_Color_Specular;
808         int loc_Color_Glow;
809         int loc_Color_Pants;
810         int loc_Color_Shirt;
811         int loc_DeferredColor_Ambient;
812         int loc_DeferredColor_Diffuse;
813         int loc_DeferredColor_Specular;
814         int loc_DeferredMod_Diffuse;
815         int loc_DeferredMod_Specular;
816         int loc_DistortScaleRefractReflect;
817         int loc_EyePosition;
818         int loc_FogColor;
819         int loc_FogHeightFade;
820         int loc_FogPlane;
821         int loc_FogPlaneViewDist;
822         int loc_FogRangeRecip;
823         int loc_LightColor;
824         int loc_LightDir;
825         int loc_LightPosition;
826         int loc_OffsetMapping_ScaleSteps;
827         int loc_PixelSize;
828         int loc_ReflectColor;
829         int loc_ReflectFactor;
830         int loc_ReflectOffset;
831         int loc_RefractColor;
832         int loc_Saturation;
833         int loc_ScreenCenterRefractReflect;
834         int loc_ScreenScaleRefractReflect;
835         int loc_ScreenToDepth;
836         int loc_ShadowMap_Parameters;
837         int loc_ShadowMap_TextureScale;
838         int loc_SpecularPower;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857 }
858 r_glsl_permutation_t;
859
860 #define SHADERPERMUTATION_HASHSIZE 256
861
862
863 // non-degradable "lightweight" shader parameters to keep the permutations simpler
864 // these can NOT degrade! only use for simple stuff
865 enum
866 {
867         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
868         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
869         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
873         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
874 };
875 #define SHADERSTATICPARMS_COUNT 7
876
877 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
878 static int shaderstaticparms_count = 0;
879
880 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
881 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
882 qboolean R_CompileShader_CheckStaticParms(void)
883 {
884         static int r_compileshader_staticparms_save[1];
885         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
886         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887
888         // detect all
889         if (r_glsl_saturation_redcompensate.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
891         if (r_glsl_vertextextureblend_usebothalphas.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
893         if (r_shadow_glossexact.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
895         if (r_glsl_postprocess.integer)
896         {
897                 if (r_glsl_postprocess_uservec1_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
899                 if (r_glsl_postprocess_uservec2_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
901                 if (r_glsl_postprocess_uservec3_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
903                 if (r_glsl_postprocess_uservec4_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
905         }
906         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
907 }
908
909 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
910         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
911                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
912         else \
913                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
914 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
915 {
916         shaderstaticparms_count = 0;
917
918         // emit all
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
926 }
927
928 /// information about each possible shader permutation
929 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
930 /// currently selected permutation
931 r_glsl_permutation_t *r_glsl_permutation;
932 /// storage for permutations linked in the hash table
933 memexpandablearray_t r_glsl_permutationarray;
934
935 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
936 {
937         //unsigned int hashdepth = 0;
938         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
939         r_glsl_permutation_t *p;
940         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
941         {
942                 if (p->mode == mode && p->permutation == permutation)
943                 {
944                         //if (hashdepth > 10)
945                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946                         return p;
947                 }
948                 //hashdepth++;
949         }
950         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
951         p->mode = mode;
952         p->permutation = permutation;
953         p->hashnext = r_glsl_permutationhash[mode][hashindex];
954         r_glsl_permutationhash[mode][hashindex] = p;
955         //if (hashdepth > 10)
956         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957         return p;
958 }
959
960 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
961 {
962         char *shaderstring;
963         if (!filename || !filename[0])
964                 return NULL;
965         if (!strcmp(filename, "glsl/default.glsl"))
966         {
967                 if (!glslshaderstring)
968                 {
969                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970                         if (glslshaderstring)
971                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
972                         else
973                                 glslshaderstring = (char *)builtinshaderstring;
974                 }
975                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
976                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
977                 return shaderstring;
978         }
979         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980         if (shaderstring)
981         {
982                 if (printfromdisknotice)
983                         Con_DPrintf("from disk %s... ", filename);
984                 return shaderstring;
985         }
986         return shaderstring;
987 }
988
989 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
990 {
991         int i;
992         int sampler;
993         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
994         char *vertexstring, *geometrystring, *fragmentstring;
995         char permutationname[256];
996         int vertstrings_count = 0;
997         int geomstrings_count = 0;
998         int fragstrings_count = 0;
999         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002
1003         if (p->compiled)
1004                 return;
1005         p->compiled = true;
1006         p->program = 0;
1007
1008         permutationname[0] = 0;
1009         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1010         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1011         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1012
1013         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1014
1015         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1016         if(vid.support.gl20shaders130)
1017         {
1018                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1019                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1020                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1021                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1022                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1023                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1024         }
1025
1026         // the first pretext is which type of shader to compile as
1027         // (later these will all be bound together as a program object)
1028         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1029         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1030         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1031
1032         // the second pretext is the mode (for example a light source)
1033         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1034         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1035         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1036         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1037
1038         // now add all the permutation pretexts
1039         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1040         {
1041                 if (permutation & (1<<i))
1042                 {
1043                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1047                 }
1048                 else
1049                 {
1050                         // keep line numbers correct
1051                         vertstrings_list[vertstrings_count++] = "\n";
1052                         geomstrings_list[geomstrings_count++] = "\n";
1053                         fragstrings_list[fragstrings_count++] = "\n";
1054                 }
1055         }
1056
1057         // add static parms
1058         R_CompileShader_AddStaticParms(mode, permutation);
1059         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         vertstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         geomstrings_count += shaderstaticparms_count;
1063         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064         fragstrings_count += shaderstaticparms_count;
1065
1066         // now append the shader text itself
1067         vertstrings_list[vertstrings_count++] = vertexstring;
1068         geomstrings_list[geomstrings_count++] = geometrystring;
1069         fragstrings_list[fragstrings_count++] = fragmentstring;
1070
1071         // if any sources were NULL, clear the respective list
1072         if (!vertexstring)
1073                 vertstrings_count = 0;
1074         if (!geometrystring)
1075                 geomstrings_count = 0;
1076         if (!fragmentstring)
1077                 fragstrings_count = 0;
1078
1079         // compile the shader program
1080         if (vertstrings_count + geomstrings_count + fragstrings_count)
1081                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1082         if (p->program)
1083         {
1084                 CHECKGLERROR
1085                 qglUseProgram(p->program);CHECKGLERROR
1086                 // look up all the uniform variable names we care about, so we don't
1087                 // have to look them up every time we set them
1088
1089                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1090                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1091                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1092                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1093                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1094                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1095                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1096                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1097                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1098                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1099                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1100                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1101                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1102                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1103                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1104                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1105                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1106                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1107                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1108                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1109                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1110                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1111                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1112                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1113                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1114                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1115                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1116                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1117                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1118                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1119                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1120                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1121                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1122                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1123                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1124                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1125                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1126                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1127                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1128                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1129                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1130                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1131                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1132                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1133                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1134                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1135                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1136                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1137                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1138                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1139                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1140                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1141                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1142                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1143                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenDepth = -1;
1199                 p->tex_Texture_ScreenNormalMap = -1;
1200                 p->tex_Texture_ScreenDiffuse = -1;
1201                 p->tex_Texture_ScreenSpecular = -1;
1202                 p->tex_Texture_ReflectMask = -1;
1203                 p->tex_Texture_ReflectCube = -1;
1204                 p->tex_Texture_BounceGrid = -1;
1205                 sampler = 0;
1206                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1207                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1208                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1209                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1210                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1211                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1212                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1217                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1218                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1219                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1220                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1221                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1222                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1223                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1224                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1225                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1226                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1227                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1228                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1233                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1234                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1235                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1236                 CHECKGLERROR
1237                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1238         }
1239         else
1240                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1241
1242         // free the strings
1243         if (vertexstring)
1244                 Mem_Free(vertexstring);
1245         if (geometrystring)
1246                 Mem_Free(geometrystring);
1247         if (fragmentstring)
1248                 Mem_Free(fragmentstring);
1249 }
1250
1251 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1252 {
1253         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1254         if (r_glsl_permutation != perm)
1255         {
1256                 r_glsl_permutation = perm;
1257                 if (!r_glsl_permutation->program)
1258                 {
1259                         if (!r_glsl_permutation->compiled)
1260                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1261                         if (!r_glsl_permutation->program)
1262                         {
1263                                 // remove features until we find a valid permutation
1264                                 int i;
1265                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1266                                 {
1267                                         // reduce i more quickly whenever it would not remove any bits
1268                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1269                                         if (!(permutation & j))
1270                                                 continue;
1271                                         permutation -= j;
1272                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1273                                         if (!r_glsl_permutation->compiled)
1274                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1275                                         if (r_glsl_permutation->program)
1276                                                 break;
1277                                 }
1278                                 if (i >= SHADERPERMUTATION_COUNT)
1279                                 {
1280                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         qglUseProgram(0);CHECKGLERROR
1283                                         return; // no bit left to clear, entire mode is broken
1284                                 }
1285                         }
1286                 }
1287                 CHECKGLERROR
1288                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1289         }
1290         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1291         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1292         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 }
1294
1295 #ifdef SUPPORTD3D
1296
1297 #ifdef SUPPORTD3D
1298 #include <d3d9.h>
1299 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1300 extern D3DCAPS9 vid_d3d9caps;
1301 #endif
1302
1303 struct r_hlsl_permutation_s;
1304 typedef struct r_hlsl_permutation_s
1305 {
1306         /// hash lookup data
1307         struct r_hlsl_permutation_s *hashnext;
1308         unsigned int mode;
1309         unsigned int permutation;
1310
1311         /// indicates if we have tried compiling this permutation already
1312         qboolean compiled;
1313         /// NULL if compilation failed
1314         IDirect3DVertexShader9 *vertexshader;
1315         IDirect3DPixelShader9 *pixelshader;
1316 }
1317 r_hlsl_permutation_t;
1318
1319 typedef enum D3DVSREGISTER_e
1320 {
1321         D3DVSREGISTER_TexMatrix = 0, // float4x4
1322         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1323         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1324         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1325         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1326         D3DVSREGISTER_ModelToLight = 20, // float4x4
1327         D3DVSREGISTER_EyePosition = 24,
1328         D3DVSREGISTER_FogPlane = 25,
1329         D3DVSREGISTER_LightDir = 26,
1330         D3DVSREGISTER_LightPosition = 27,
1331 }
1332 D3DVSREGISTER_t;
1333
1334 typedef enum D3DPSREGISTER_e
1335 {
1336         D3DPSREGISTER_Alpha = 0,
1337         D3DPSREGISTER_BloomBlur_Parameters = 1,
1338         D3DPSREGISTER_ClientTime = 2,
1339         D3DPSREGISTER_Color_Ambient = 3,
1340         D3DPSREGISTER_Color_Diffuse = 4,
1341         D3DPSREGISTER_Color_Specular = 5,
1342         D3DPSREGISTER_Color_Glow = 6,
1343         D3DPSREGISTER_Color_Pants = 7,
1344         D3DPSREGISTER_Color_Shirt = 8,
1345         D3DPSREGISTER_DeferredColor_Ambient = 9,
1346         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1347         D3DPSREGISTER_DeferredColor_Specular = 11,
1348         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1349         D3DPSREGISTER_DeferredMod_Specular = 13,
1350         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1351         D3DPSREGISTER_EyePosition = 15, // unused
1352         D3DPSREGISTER_FogColor = 16,
1353         D3DPSREGISTER_FogHeightFade = 17,
1354         D3DPSREGISTER_FogPlane = 18,
1355         D3DPSREGISTER_FogPlaneViewDist = 19,
1356         D3DPSREGISTER_FogRangeRecip = 20,
1357         D3DPSREGISTER_LightColor = 21,
1358         D3DPSREGISTER_LightDir = 22, // unused
1359         D3DPSREGISTER_LightPosition = 23,
1360         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1361         D3DPSREGISTER_PixelSize = 25,
1362         D3DPSREGISTER_ReflectColor = 26,
1363         D3DPSREGISTER_ReflectFactor = 27,
1364         D3DPSREGISTER_ReflectOffset = 28,
1365         D3DPSREGISTER_RefractColor = 29,
1366         D3DPSREGISTER_Saturation = 30,
1367         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1368         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1369         D3DPSREGISTER_ScreenToDepth = 33,
1370         D3DPSREGISTER_ShadowMap_Parameters = 34,
1371         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1372         D3DPSREGISTER_SpecularPower = 36,
1373         D3DPSREGISTER_UserVec1 = 37,
1374         D3DPSREGISTER_UserVec2 = 38,
1375         D3DPSREGISTER_UserVec3 = 39,
1376         D3DPSREGISTER_UserVec4 = 40,
1377         D3DPSREGISTER_ViewTintColor = 41,
1378         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1379         D3DPSREGISTER_BloomColorSubtract = 43,
1380         D3DPSREGISTER_ViewToLight = 44, // float4x4
1381         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1382         D3DPSREGISTER_NormalmapScrollBlend = 52,
1383         // next at 53
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         qboolean debugshader = gl_paranoid.integer != 0;
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (!debugshader)
1474         {
1475                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1477         }
1478         if ((!vsbin && vertstring) || (!psbin && fragstring))
1479         {
1480                 const char* dllnames_d3dx9 [] =
1481                 {
1482                         "d3dx9_43.dll",
1483                         "d3dx9_42.dll",
1484                         "d3dx9_41.dll",
1485                         "d3dx9_40.dll",
1486                         "d3dx9_39.dll",
1487                         "d3dx9_38.dll",
1488                         "d3dx9_37.dll",
1489                         "d3dx9_36.dll",
1490                         "d3dx9_35.dll",
1491                         "d3dx9_34.dll",
1492                         "d3dx9_33.dll",
1493                         "d3dx9_32.dll",
1494                         "d3dx9_31.dll",
1495                         "d3dx9_30.dll",
1496                         "d3dx9_29.dll",
1497                         "d3dx9_28.dll",
1498                         "d3dx9_27.dll",
1499                         "d3dx9_26.dll",
1500                         "d3dx9_25.dll",
1501                         "d3dx9_24.dll",
1502                         NULL
1503                 };
1504                 dllhandle_t d3dx9_dll = NULL;
1505                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 dllfunction_t d3dx9_dllfuncs[] =
1509                 {
1510                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1511                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1512                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1513                         {NULL, NULL}
1514                 };
1515                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1516                 {
1517                         DWORD shaderflags = 0;
1518                         if (debugshader)
1519                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522                         if (vertstring && vertstring[0])
1523                         {
1524                                 if (debugshader)
1525                                 {
1526 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530                                 }
1531                                 else
1532                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533                                 if (vsbuffer)
1534                                 {
1535                                         vsbinsize = vsbuffer->GetBufferSize();
1536                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538                                         vsbuffer->Release();
1539                                 }
1540                                 if (vslog)
1541                                 {
1542                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1544                                         vslog->Release();
1545                                 }
1546                         }
1547                         if (fragstring && fragstring[0])
1548                         {
1549                                 if (debugshader)
1550                                 {
1551 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555                                 }
1556                                 else
1557                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558                                 if (psbuffer)
1559                                 {
1560                                         psbinsize = psbuffer->GetBufferSize();
1561                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563                                         psbuffer->Release();
1564                                 }
1565                                 if (pslog)
1566                                 {
1567                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1569                                         pslog->Release();
1570                                 }
1571                         }
1572                         Sys_UnloadLibrary(&d3dx9_dll);
1573                 }
1574                 else
1575                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1576         }
1577         if (vsbin && psbin)
1578         {
1579                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580                 if (FAILED(vsresult))
1581                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583                 if (FAILED(psresult))
1584                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1585         }
1586         // free the shader data
1587         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 }
1590
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1592 {
1593         int i;
1594         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595         int vertstring_length = 0;
1596         int geomstring_length = 0;
1597         int fragstring_length = 0;
1598         char *t;
1599         char *vertexstring, *geometrystring, *fragmentstring;
1600         char *vertstring, *geomstring, *fragstring;
1601         char permutationname[256];
1602         char cachename[256];
1603         int vertstrings_count = 0;
1604         int geomstrings_count = 0;
1605         int fragstrings_count = 0;
1606         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609
1610         if (p->compiled)
1611                 return;
1612         p->compiled = true;
1613         p->vertexshader = NULL;
1614         p->pixelshader = NULL;
1615
1616         permutationname[0] = 0;
1617         cachename[0] = 0;
1618         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1621
1622         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623         strlcat(cachename, "hlsl/", sizeof(cachename));
1624
1625         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626         vertstrings_count = 0;
1627         geomstrings_count = 0;
1628         fragstrings_count = 0;
1629         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1632
1633         // the first pretext is which type of shader to compile as
1634         // (later these will all be bound together as a program object)
1635         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1638
1639         // the second pretext is the mode (for example a light source)
1640         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644         strlcat(cachename, modeinfo->name, sizeof(cachename));
1645
1646         // now add all the permutation pretexts
1647         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1648         {
1649                 if (permutation & (1<<i))
1650                 {
1651                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1656                 }
1657                 else
1658                 {
1659                         // keep line numbers correct
1660                         vertstrings_list[vertstrings_count++] = "\n";
1661                         geomstrings_list[geomstrings_count++] = "\n";
1662                         fragstrings_list[fragstrings_count++] = "\n";
1663                 }
1664         }
1665
1666         // add static parms
1667         R_CompileShader_AddStaticParms(mode, permutation);
1668         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         vertstrings_count += shaderstaticparms_count;
1670         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         geomstrings_count += shaderstaticparms_count;
1672         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         fragstrings_count += shaderstaticparms_count;
1674
1675         // replace spaces in the cachename with _ characters
1676         for (i = 0;cachename[i];i++)
1677                 if (cachename[i] == ' ')
1678                         cachename[i] = '_';
1679
1680         // now append the shader text itself
1681         vertstrings_list[vertstrings_count++] = vertexstring;
1682         geomstrings_list[geomstrings_count++] = geometrystring;
1683         fragstrings_list[fragstrings_count++] = fragmentstring;
1684
1685         // if any sources were NULL, clear the respective list
1686         if (!vertexstring)
1687                 vertstrings_count = 0;
1688         if (!geometrystring)
1689                 geomstrings_count = 0;
1690         if (!fragmentstring)
1691                 fragstrings_count = 0;
1692
1693         vertstring_length = 0;
1694         for (i = 0;i < vertstrings_count;i++)
1695                 vertstring_length += strlen(vertstrings_list[i]);
1696         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1699
1700         geomstring_length = 0;
1701         for (i = 0;i < geomstrings_count;i++)
1702                 geomstring_length += strlen(geomstrings_list[i]);
1703         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1706
1707         fragstring_length = 0;
1708         for (i = 0;i < fragstrings_count;i++)
1709                 fragstring_length += strlen(fragstrings_list[i]);
1710         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1713
1714         // try to load the cached shader, or generate one
1715         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1716
1717         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1719         else
1720                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1721
1722         // free the strings
1723         if (vertstring)
1724                 Mem_Free(vertstring);
1725         if (geomstring)
1726                 Mem_Free(geomstring);
1727         if (fragstring)
1728                 Mem_Free(fragstring);
1729         if (vertexstring)
1730                 Mem_Free(vertexstring);
1731         if (geometrystring)
1732                 Mem_Free(geometrystring);
1733         if (fragmentstring)
1734                 Mem_Free(fragmentstring);
1735 }
1736
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1743
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1750
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1752 {
1753         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754         if (r_hlsl_permutation != perm)
1755         {
1756                 r_hlsl_permutation = perm;
1757                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                 {
1759                         if (!r_hlsl_permutation->compiled)
1760                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1762                         {
1763                                 // remove features until we find a valid permutation
1764                                 int i;
1765                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1766                                 {
1767                                         // reduce i more quickly whenever it would not remove any bits
1768                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769                                         if (!(permutation & j))
1770                                                 continue;
1771                                         permutation -= j;
1772                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773                                         if (!r_hlsl_permutation->compiled)
1774                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1776                                                 break;
1777                                 }
1778                                 if (i >= SHADERPERMUTATION_COUNT)
1779                                 {
1780                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         return; // no bit left to clear, entire mode is broken
1783                                 }
1784                         }
1785                 }
1786                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1788         }
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1792 }
1793 #endif
1794
1795 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1796 {
1797         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1801 }
1802
1803 void R_GLSL_Restart_f(void)
1804 {
1805         unsigned int i, limit;
1806         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807                 Mem_Free(glslshaderstring);
1808         glslshaderstring = NULL;
1809         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810                 Mem_Free(hlslshaderstring);
1811         hlslshaderstring = NULL;
1812         switch(vid.renderpath)
1813         {
1814         case RENDERPATH_D3D9:
1815 #ifdef SUPPORTD3D
1816                 {
1817                         r_hlsl_permutation_t *p;
1818                         r_hlsl_permutation = NULL;
1819                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820                         for (i = 0;i < limit;i++)
1821                         {
1822                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1823                                 {
1824                                         if (p->vertexshader)
1825                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1826                                         if (p->pixelshader)
1827                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1828                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1829                                 }
1830                         }
1831                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1832                 }
1833 #endif
1834                 break;
1835         case RENDERPATH_D3D10:
1836                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837                 break;
1838         case RENDERPATH_D3D11:
1839                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840                 break;
1841         case RENDERPATH_GL20:
1842         case RENDERPATH_GLES2:
1843                 {
1844                         r_glsl_permutation_t *p;
1845                         r_glsl_permutation = NULL;
1846                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847                         for (i = 0;i < limit;i++)
1848                         {
1849                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1850                                 {
1851                                         GL_Backend_FreeProgram(p->program);
1852                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1853                                 }
1854                         }
1855                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1856                 }
1857                 break;
1858         case RENDERPATH_GL11:
1859         case RENDERPATH_GL13:
1860         case RENDERPATH_GLES1:
1861                 break;
1862         case RENDERPATH_SOFT:
1863                 break;
1864         }
1865 }
1866
1867 void R_GLSL_DumpShader_f(void)
1868 {
1869         int i;
1870         qfile_t *file;
1871
1872         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1873         if (file)
1874         {
1875                 FS_Print(file, "/* The engine may define the following macros:\n");
1876                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877                 for (i = 0;i < SHADERMODE_COUNT;i++)
1878                         FS_Print(file, glslshadermodeinfo[i].pretext);
1879                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880                         FS_Print(file, shaderpermutationinfo[i].pretext);
1881                 FS_Print(file, "*/\n");
1882                 FS_Print(file, builtinshaderstring);
1883                 FS_Close(file);
1884                 Con_Printf("glsl/default.glsl written\n");
1885         }
1886         else
1887                 Con_Printf("failed to write to glsl/default.glsl\n");
1888
1889         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinhlslshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("hlsl/default.hlsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1905 }
1906
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1908 {
1909         unsigned int permutation = 0;
1910         if (r_trippy.integer && !notrippy)
1911                 permutation |= SHADERPERMUTATION_TRIPPY;
1912         permutation |= SHADERPERMUTATION_VIEWTINT;
1913         if (first)
1914                 permutation |= SHADERPERMUTATION_DIFFUSE;
1915         if (second)
1916                 permutation |= SHADERPERMUTATION_SPECULAR;
1917         if (texturemode == GL_MODULATE)
1918                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1919         else if (texturemode == GL_ADD)
1920                 permutation |= SHADERPERMUTATION_GLOW;
1921         else if (texturemode == GL_DECAL)
1922                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1923         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1924                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1925         if (!second)
1926                 texturemode = GL_MODULATE;
1927         if (vid.allowalphatocoverage)
1928                 GL_AlphaToCoverage(false);
1929         switch (vid.renderpath)
1930         {
1931         case RENDERPATH_D3D9:
1932 #ifdef SUPPORTD3D
1933                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1934                 R_Mesh_TexBind(GL20TU_FIRST , first );
1935                 R_Mesh_TexBind(GL20TU_SECOND, second);
1936                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1937                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1938 #endif
1939                 break;
1940         case RENDERPATH_D3D10:
1941                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942                 break;
1943         case RENDERPATH_D3D11:
1944                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_GL20:
1947         case RENDERPATH_GLES2:
1948                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1949                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1950                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1951                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1952                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1953                 break;
1954         case RENDERPATH_GL13:
1955         case RENDERPATH_GLES1:
1956                 R_Mesh_TexBind(0, first );
1957                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1958                 R_Mesh_TexBind(1, second);
1959                 if (second)
1960                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1961                 break;
1962         case RENDERPATH_GL11:
1963                 R_Mesh_TexBind(0, first );
1964                 break;
1965         case RENDERPATH_SOFT:
1966                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1967                 R_Mesh_TexBind(GL20TU_FIRST , first );
1968                 R_Mesh_TexBind(GL20TU_SECOND, second);
1969                 break;
1970         }
1971 }
1972
1973 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1974 {
1975         unsigned int permutation = 0;
1976         if (r_trippy.integer && !notrippy)
1977                 permutation |= SHADERPERMUTATION_TRIPPY;
1978         if (vid.allowalphatocoverage)
1979                 GL_AlphaToCoverage(false);
1980         switch (vid.renderpath)
1981         {
1982         case RENDERPATH_D3D9:
1983 #ifdef SUPPORTD3D
1984                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1985 #endif
1986                 break;
1987         case RENDERPATH_D3D10:
1988                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_D3D11:
1991                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992                 break;
1993         case RENDERPATH_GL20:
1994         case RENDERPATH_GLES2:
1995                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1996                 break;
1997         case RENDERPATH_GL13:
1998         case RENDERPATH_GLES1:
1999                 R_Mesh_TexBind(0, 0);
2000                 R_Mesh_TexBind(1, 0);
2001                 break;
2002         case RENDERPATH_GL11:
2003                 R_Mesh_TexBind(0, 0);
2004                 break;
2005         case RENDERPATH_SOFT:
2006                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2007                 break;
2008         }
2009 }
2010
2011 void R_SetupShader_ShowDepth(qboolean notrippy)
2012 {
2013         int permutation = 0;
2014         if (r_trippy.integer && !notrippy)
2015                 permutation |= SHADERPERMUTATION_TRIPPY;
2016         if (vid.allowalphatocoverage)
2017                 GL_AlphaToCoverage(false);
2018         switch (vid.renderpath)
2019         {
2020         case RENDERPATH_D3D9:
2021 #ifdef SUPPORTHLSL
2022                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2023 #endif
2024                 break;
2025         case RENDERPATH_D3D10:
2026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                 break;
2028         case RENDERPATH_D3D11:
2029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030                 break;
2031         case RENDERPATH_GL20:
2032         case RENDERPATH_GLES2:
2033                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2034                 break;
2035         case RENDERPATH_GL13:
2036         case RENDERPATH_GLES1:
2037                 break;
2038         case RENDERPATH_GL11:
2039                 break;
2040         case RENDERPATH_SOFT:
2041                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2042                 break;
2043         }
2044 }
2045
2046 extern qboolean r_shadow_usingdeferredprepass;
2047 extern cvar_t r_shadow_deferred_8bitrange;
2048 extern rtexture_t *r_shadow_attenuationgradienttexture;
2049 extern rtexture_t *r_shadow_attenuation2dtexture;
2050 extern rtexture_t *r_shadow_attenuation3dtexture;
2051 extern qboolean r_shadow_usingshadowmap2d;
2052 extern qboolean r_shadow_usingshadowmaportho;
2053 extern float r_shadow_shadowmap_texturescale[2];
2054 extern float r_shadow_shadowmap_parameters[4];
2055 extern qboolean r_shadow_shadowmapvsdct;
2056 extern qboolean r_shadow_shadowmapsampler;
2057 extern int r_shadow_shadowmappcf;
2058 extern rtexture_t *r_shadow_shadowmap2dtexture;
2059 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2060 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2061 extern matrix4x4_t r_shadow_shadowmapmatrix;
2062 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2063 extern int r_shadow_prepass_width;
2064 extern int r_shadow_prepass_height;
2065 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2066 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2067 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2068 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2069 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2070
2071 #define BLENDFUNC_ALLOWS_COLORMOD      1
2072 #define BLENDFUNC_ALLOWS_FOG           2
2073 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2074 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2075 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2076 static int R_BlendFuncFlags(int src, int dst)
2077 {
2078         int r = 0;
2079
2080         // a blendfunc allows colormod if:
2081         // a) it can never keep the destination pixel invariant, or
2082         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2083         // this is to prevent unintended side effects from colormod
2084
2085         // a blendfunc allows fog if:
2086         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2087         // this is to prevent unintended side effects from fog
2088
2089         // these checks are the output of fogeval.pl
2090
2091         r |= BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2101         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2107         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113
2114         return r;
2115 }
2116
2117 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)
2118 {
2119         // select a permutation of the lighting shader appropriate to this
2120         // combination of texture, entity, light source, and fogging, only use the
2121         // minimum features necessary to avoid wasting rendering time in the
2122         // fragment shader on features that are not being used
2123         unsigned int permutation = 0;
2124         unsigned int mode = 0;
2125         int blendfuncflags;
2126         static float dummy_colormod[3] = {1, 1, 1};
2127         float *colormod = rsurface.colormod;
2128         float m16f[16];
2129         matrix4x4_t tempmatrix;
2130         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2131         if (r_trippy.integer && !notrippy)
2132                 permutation |= SHADERPERMUTATION_TRIPPY;
2133         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2134                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2135         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2136                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2137         if (rsurfacepass == RSURFPASS_BACKGROUND)
2138         {
2139                 // distorted background
2140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2141                 {
2142                         mode = SHADERMODE_WATER;
2143                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2144                         {
2145                                 // this is the right thing to do for wateralpha
2146                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2147                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2148                         }
2149                         else
2150                         {
2151                                 // this is the right thing to do for entity alpha
2152                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         }
2155                 }
2156                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2157                 {
2158                         mode = SHADERMODE_REFRACTION;
2159                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                 }
2162                 else
2163                 {
2164                         mode = SHADERMODE_GENERIC;
2165                         permutation |= SHADERPERMUTATION_DIFFUSE;
2166                         GL_BlendFunc(GL_ONE, GL_ZERO);
2167                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2168                 }
2169                 if (vid.allowalphatocoverage)
2170                         GL_AlphaToCoverage(false);
2171         }
2172         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2173         {
2174                 if (r_glsl_offsetmapping.integer)
2175                 {
2176                         switch(rsurface.texture->offsetmapping)
2177                         {
2178                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2179                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181                         case OFFSETMAPPING_OFF: break;
2182                         }
2183                 }
2184                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2185                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2186                 // normalmap (deferred prepass), may use alpha test on diffuse
2187                 mode = SHADERMODE_DEFERREDGEOMETRY;
2188                 GL_BlendFunc(GL_ONE, GL_ZERO);
2189                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2190                 if (vid.allowalphatocoverage)
2191                         GL_AlphaToCoverage(false);
2192         }
2193         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // light source
2208                 mode = SHADERMODE_LIGHTSOURCE;
2209                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2210                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2211                 if (diffusescale > 0)
2212                         permutation |= SHADERPERMUTATION_DIFFUSE;
2213                 if (specularscale > 0)
2214                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2215                 if (r_refdef.fogenabled)
2216                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217                 if (rsurface.texture->colormapping)
2218                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2219                 if (r_shadow_usingshadowmap2d)
2220                 {
2221                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222                         if(r_shadow_shadowmapvsdct)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2224
2225                         if (r_shadow_shadowmapsampler)
2226                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2227                         if (r_shadow_shadowmappcf > 1)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2229                         else if (r_shadow_shadowmappcf)
2230                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2231                 }
2232                 if (rsurface.texture->reflectmasktexture)
2233                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2235                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2236                 if (vid.allowalphatocoverage)
2237                         GL_AlphaToCoverage(false);
2238         }
2239         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2240         {
2241                 if (r_glsl_offsetmapping.integer)
2242                 {
2243                         switch(rsurface.texture->offsetmapping)
2244                         {
2245                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2246                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_OFF: break;
2249                         }
2250                 }
2251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253                 // unshaded geometry (fullbright or ambient model lighting)
2254                 mode = SHADERMODE_FLATCOLOR;
2255                 ambientscale = diffusescale = specularscale = 0;
2256                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257                         permutation |= SHADERPERMUTATION_GLOW;
2258                 if (r_refdef.fogenabled)
2259                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260                 if (rsurface.texture->colormapping)
2261                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2262                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2263                 {
2264                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2266
2267                         if (r_shadow_shadowmapsampler)
2268                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269                         if (r_shadow_shadowmappcf > 1)
2270                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271                         else if (r_shadow_shadowmappcf)
2272                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2273                 }
2274                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275                         permutation |= SHADERPERMUTATION_REFLECTION;
2276                 if (rsurface.texture->reflectmasktexture)
2277                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280                 // when using alphatocoverage, we don't need alphakill
2281                 if (vid.allowalphatocoverage)
2282                 {
2283                         if (r_transparent_alphatocoverage.integer)
2284                         {
2285                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2286                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2287                         }
2288                         else
2289                                 GL_AlphaToCoverage(false);
2290                 }
2291         }
2292         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2293         {
2294                 if (r_glsl_offsetmapping.integer)
2295                 {
2296                         switch(rsurface.texture->offsetmapping)
2297                         {
2298                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_OFF: break;
2302                         }
2303                 }
2304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306                 // directional model lighting
2307                 mode = SHADERMODE_LIGHTDIRECTION;
2308                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2309                         permutation |= SHADERPERMUTATION_GLOW;
2310                 permutation |= SHADERPERMUTATION_DIFFUSE;
2311                 if (specularscale > 0)
2312                         permutation |= SHADERPERMUTATION_SPECULAR;
2313                 if (r_refdef.fogenabled)
2314                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315                 if (rsurface.texture->colormapping)
2316                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2317                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2318                 {
2319                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2321
2322                         if (r_shadow_shadowmapsampler)
2323                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324                         if (r_shadow_shadowmappcf > 1)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326                         else if (r_shadow_shadowmappcf)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330                         permutation |= SHADERPERMUTATION_REFLECTION;
2331                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333                 if (rsurface.texture->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2336                 {
2337                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338                         if (r_shadow_bouncegriddirectional)
2339                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2340                 }
2341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 // when using alphatocoverage, we don't need alphakill
2344                 if (vid.allowalphatocoverage)
2345                 {
2346                         if (r_transparent_alphatocoverage.integer)
2347                         {
2348                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2349                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2350                         }
2351                         else
2352                                 GL_AlphaToCoverage(false);
2353                 }
2354         }
2355         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2356         {
2357                 if (r_glsl_offsetmapping.integer)
2358                 {
2359                         switch(rsurface.texture->offsetmapping)
2360                         {
2361                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364                         case OFFSETMAPPING_OFF: break;
2365                         }
2366                 }
2367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369                 // ambient model lighting
2370                 mode = SHADERMODE_LIGHTDIRECTION;
2371                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372                         permutation |= SHADERPERMUTATION_GLOW;
2373                 if (r_refdef.fogenabled)
2374                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375                 if (rsurface.texture->colormapping)
2376                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2377                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2378                 {
2379                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2381
2382                         if (r_shadow_shadowmapsampler)
2383                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384                         if (r_shadow_shadowmappcf > 1)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386                         else if (r_shadow_shadowmappcf)
2387                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2388                 }
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390                         permutation |= SHADERPERMUTATION_REFLECTION;
2391                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393                 if (rsurface.texture->reflectmasktexture)
2394                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2396                 {
2397                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2398                         if (r_shadow_bouncegriddirectional)
2399                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2400                 }
2401                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403                 // when using alphatocoverage, we don't need alphakill
2404                 if (vid.allowalphatocoverage)
2405                 {
2406                         if (r_transparent_alphatocoverage.integer)
2407                         {
2408                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2409                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2410                         }
2411                         else
2412                                 GL_AlphaToCoverage(false);
2413                 }
2414         }
2415         else
2416         {
2417                 if (r_glsl_offsetmapping.integer)
2418                 {
2419                         switch(rsurface.texture->offsetmapping)
2420                         {
2421                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2422                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424                         case OFFSETMAPPING_OFF: break;
2425                         }
2426                 }
2427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2429                 // lightmapped wall
2430                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2431                         permutation |= SHADERPERMUTATION_GLOW;
2432                 if (r_refdef.fogenabled)
2433                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2434                 if (rsurface.texture->colormapping)
2435                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2436                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2437                 {
2438                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2439                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2440
2441                         if (r_shadow_shadowmapsampler)
2442                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2443                         if (r_shadow_shadowmappcf > 1)
2444                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2445                         else if (r_shadow_shadowmappcf)
2446                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2447                 }
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449                         permutation |= SHADERPERMUTATION_REFLECTION;
2450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452                 if (rsurface.texture->reflectmasktexture)
2453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454                 if (FAKELIGHT_ENABLED)
2455                 {
2456                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457                         mode = SHADERMODE_FAKELIGHT;
2458                         permutation |= SHADERPERMUTATION_DIFFUSE;
2459                         if (specularscale > 0)
2460                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2461                 }
2462                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2463                 {
2464                         // deluxemapping (light direction texture)
2465                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2467                         else
2468                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 2)
2474                 {
2475                         // fake deluxemapping (uniform light direction in tangentspace)
2476                         if (rsurface.uselightmaptexture)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (rsurface.uselightmaptexture)
2485                 {
2486                         // ordinary lightmapping (q1bsp, q3bsp)
2487                         mode = SHADERMODE_LIGHTMAP;
2488                 }
2489                 else
2490                 {
2491                         // ordinary vertex coloring (q3bsp)
2492                         mode = SHADERMODE_VERTEXCOLOR;
2493                 }
2494                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2495                 {
2496                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497                         if (r_shadow_bouncegriddirectional)
2498                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2499                 }
2500                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 // when using alphatocoverage, we don't need alphakill
2503                 if (vid.allowalphatocoverage)
2504                 {
2505                         if (r_transparent_alphatocoverage.integer)
2506                         {
2507                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2509                         }
2510                         else
2511                                 GL_AlphaToCoverage(false);
2512                 }
2513         }
2514         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515                 colormod = dummy_colormod;
2516         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520         switch(vid.renderpath)
2521         {
2522         case RENDERPATH_D3D9:
2523 #ifdef SUPPORTD3D
2524                 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);
2525                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                 }
2533                 else
2534                 {
2535                         if (mode == SHADERMODE_LIGHTDIRECTION)
2536                         {
2537                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2538                         }
2539                 }
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2545
2546                 if (mode == SHADERMODE_LIGHTSOURCE)
2547                 {
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2553
2554                         // additive passes are only darkened by fog, not tinted
2555                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2557                 }
2558                 else
2559                 {
2560                         if (mode == SHADERMODE_FLATCOLOR)
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2563                         }
2564                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2565                         {
2566                                 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]);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2568                                 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);
2569                                 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);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2573                         }
2574                         else
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581                         }
2582                         // additive passes are only darkened by fog, not tinted
2583                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2585                         else
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2587                         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);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595                         if (mode == SHADERMODE_WATER)
2596                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2597                 }
2598                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601                 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));
2602                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603                 if (rsurface.texture->pantstexture)
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2605                 else
2606                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607                 if (rsurface.texture->shirttexture)
2608                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2609                 else
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2620                         );
2621                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2622                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2623
2624                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2625                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2626                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2627                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2632                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2633                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2634                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2635                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2636                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2637                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2638                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2639                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2640                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2641                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2642                 {
2643                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2644                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2645                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2646                 }
2647                 else
2648                 {
2649                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2650                 }
2651 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2652 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2653                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2654                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2655                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2656                 {
2657                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2658                         if (rsurface.rtlight)
2659                         {
2660                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2661                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2662                         }
2663                 }
2664 #endif
2665                 break;
2666         case RENDERPATH_D3D10:
2667                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2668                 break;
2669         case RENDERPATH_D3D11:
2670                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2671                 break;
2672         case RENDERPATH_GL20:
2673         case RENDERPATH_GLES2:
2674                 if (!vid.useinterleavedarrays)
2675                 {
2676                         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);
2677                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2678                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2684                 }
2685                 else
2686                 {
2687                         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);
2688                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2689                 }
2690                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2691                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692                 if (mode == SHADERMODE_LIGHTSOURCE)
2693                 {
2694                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2697                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2698                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2699                         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);
2700         
2701                         // additive passes are only darkened by fog, not tinted
2702                         if (r_glsl_permutation->loc_FogColor >= 0)
2703                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2705                 }
2706                 else
2707                 {
2708                         if (mode == SHADERMODE_FLATCOLOR)
2709                         {
2710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2711                         }
2712                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2713                         {
2714                                 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]);
2715                                 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]);
2716                                 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);
2717                                 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);
2718                                 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);
2719                                 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]);
2720                                 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]);
2721                         }
2722                         else
2723                         {
2724                                 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]);
2725                                 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]);
2726                                 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);
2727                                 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);
2728                                 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);
2729                         }
2730                         // additive passes are only darkened by fog, not tinted
2731                         if (r_glsl_permutation->loc_FogColor >= 0)
2732                         {
2733                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2735                                 else
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2737                         }
2738                         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);
2739                         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]);
2740                         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]);
2741                         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]);
2742                         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]);
2743                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2744                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2745                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2746                         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]);
2747                 }
2748                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751                 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]);
2752                 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]);
2753
2754                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2755                 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));
2756                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2757                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2758                 {
2759                         if (rsurface.texture->pantstexture)
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2761                         else
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2763                 }
2764                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2765                 {
2766                         if (rsurface.texture->shirttexture)
2767                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2768                         else
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2770                 }
2771                 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]);
2772                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2773                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2774                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2775                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2776                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2777                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2780                         );
2781                 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]);
2782                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2783                 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);}
2784                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2785
2786                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2787                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2788                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2789                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2790                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2791                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2792                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2797                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2798                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2799                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2800                 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);
2801                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2802                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2803                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2806                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2807                 {
2808                         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);
2809                         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);
2810                         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);
2811                 }
2812                 else
2813                 {
2814                         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);
2815                 }
2816                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2817                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2818                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2819                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2820                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2821                 {
2822                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2823                         if (rsurface.rtlight)
2824                         {
2825                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2826                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2827                         }
2828                 }
2829                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2830                 CHECKGLERROR
2831                 break;
2832         case RENDERPATH_GL11:
2833         case RENDERPATH_GL13:
2834         case RENDERPATH_GLES1:
2835                 break;
2836         case RENDERPATH_SOFT:
2837                 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);
2838                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2839                 R_SetupShader_SetPermutationSoft(mode, permutation);
2840                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2841                 if (mode == SHADERMODE_LIGHTSOURCE)
2842                 {
2843                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2849         
2850                         // additive passes are only darkened by fog, not tinted
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2852                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2853                 }
2854                 else
2855                 {
2856                         if (mode == SHADERMODE_FLATCOLOR)
2857                         {
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2859                         }
2860                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2861                         {
2862                                 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]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2864                                 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);
2865                                 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);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867                                 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]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2869                         }
2870                         else
2871                         {
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2874                                 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);
2875                                 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);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2877                         }
2878                         // additive passes are only darkened by fog, not tinted
2879                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2881                         else
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2883                         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);
2884                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2885                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2886                         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]);
2887                         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]);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2889                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2890                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2891                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2892                 }
2893                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2894                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2895                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2896                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897                 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]);
2898
2899                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2900                 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));
2901                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2902                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2903                 {
2904                         if (rsurface.texture->pantstexture)
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2906                         else
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2908                 }
2909                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2910                 {
2911                         if (rsurface.texture->shirttexture)
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2913                         else
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2915                 }
2916                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2920                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2921                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2922                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2925                         );
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2928
2929                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2930                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2931                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2932                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2936                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2938                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2940                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2942                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2943                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2946                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2947                 {
2948                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952                 else
2953                 {
2954                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2957 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2959                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2960                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2961                 {
2962                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2963                         if (rsurface.rtlight)
2964                         {
2965                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2966                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2967                         }
2968                 }
2969                 break;
2970         }
2971 }
2972
2973 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2974 {
2975         // select a permutation of the lighting shader appropriate to this
2976         // combination of texture, entity, light source, and fogging, only use the
2977         // minimum features necessary to avoid wasting rendering time in the
2978         // fragment shader on features that are not being used
2979         unsigned int permutation = 0;
2980         unsigned int mode = 0;
2981         const float *lightcolorbase = rtlight->currentcolor;
2982         float ambientscale = rtlight->ambientscale;
2983         float diffusescale = rtlight->diffusescale;
2984         float specularscale = rtlight->specularscale;
2985         // this is the location of the light in view space
2986         vec3_t viewlightorigin;
2987         // this transforms from view space (camera) to light space (cubemap)
2988         matrix4x4_t viewtolight;
2989         matrix4x4_t lighttoview;
2990         float viewtolight16f[16];
2991         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2992         // light source
2993         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2994         if (rtlight->currentcubemap != r_texture_whitecube)
2995                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2996         if (diffusescale > 0)
2997                 permutation |= SHADERPERMUTATION_DIFFUSE;
2998         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2999                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3000         if (r_shadow_usingshadowmap2d)
3001         {
3002                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3003                 if (r_shadow_shadowmapvsdct)
3004                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3005
3006                 if (r_shadow_shadowmapsampler)
3007                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3008                 if (r_shadow_shadowmappcf > 1)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3010                 else if (r_shadow_shadowmappcf)
3011                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3012         }
3013         if (vid.allowalphatocoverage)
3014                 GL_AlphaToCoverage(false);
3015         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3016         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3017         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3018         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3019         switch(vid.renderpath)
3020         {
3021         case RENDERPATH_D3D9:
3022 #ifdef SUPPORTD3D
3023                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3025                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3028                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3029                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3030                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3031                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3032                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3033                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3034
3035                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3036                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3037                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3038                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3039                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3040                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3041 #endif
3042                 break;
3043         case RENDERPATH_D3D10:
3044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_D3D11:
3047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3048                 break;
3049         case RENDERPATH_GL20:
3050         case RENDERPATH_GLES2:
3051                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3054                 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);
3055                 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);
3056                 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);
3057                 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]);
3058                 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]);
3059                 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));
3060                 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]);
3061                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3062
3063                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3064                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3065                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3066                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3067                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3068                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3069                 break;
3070         case RENDERPATH_GL11:
3071         case RENDERPATH_GL13:
3072         case RENDERPATH_GLES1:
3073                 break;
3074         case RENDERPATH_SOFT:
3075                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3080                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3081                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3082                 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]);
3083                 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));
3084                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3085                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3086
3087                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3088                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3089                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3090                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3091                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3092                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3093                 break;
3094         }
3095 }
3096
3097 #define SKINFRAME_HASH 1024
3098
3099 typedef struct
3100 {
3101         int loadsequence; // incremented each level change
3102         memexpandablearray_t array;
3103         skinframe_t *hash[SKINFRAME_HASH];
3104 }
3105 r_skinframe_t;
3106 r_skinframe_t r_skinframe;
3107
3108 void R_SkinFrame_PrepareForPurge(void)
3109 {
3110         r_skinframe.loadsequence++;
3111         // wrap it without hitting zero
3112         if (r_skinframe.loadsequence >= 200)
3113                 r_skinframe.loadsequence = 1;
3114 }
3115
3116 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3117 {
3118         if (!skinframe)
3119                 return;
3120         // mark the skinframe as used for the purging code
3121         skinframe->loadsequence = r_skinframe.loadsequence;
3122 }
3123
3124 void R_SkinFrame_Purge(void)
3125 {
3126         int i;
3127         skinframe_t *s;
3128         for (i = 0;i < SKINFRAME_HASH;i++)
3129         {
3130                 for (s = r_skinframe.hash[i];s;s = s->next)
3131                 {
3132                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3133                         {
3134                                 if (s->merged == s->base)
3135                                         s->merged = NULL;
3136                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3137                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3138                                 R_PurgeTexture(s->merged);s->merged = NULL;
3139                                 R_PurgeTexture(s->base  );s->base   = NULL;
3140                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3141                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3142                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3143                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3144                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3145                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3146                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3147                                 s->loadsequence = 0;
3148                         }
3149                 }
3150         }
3151 }
3152
3153 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3154         skinframe_t *item;
3155         char basename[MAX_QPATH];
3156
3157         Image_StripImageExtension(name, basename, sizeof(basename));
3158
3159         if( last == NULL ) {
3160                 int hashindex;
3161                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3162                 item = r_skinframe.hash[hashindex];
3163         } else {
3164                 item = last->next;
3165         }
3166
3167         // linearly search through the hash bucket
3168         for( ; item ; item = item->next ) {
3169                 if( !strcmp( item->basename, basename ) ) {
3170                         return item;
3171                 }
3172         }
3173         return NULL;
3174 }
3175
3176 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3177 {
3178         skinframe_t *item;
3179         int hashindex;
3180         char basename[MAX_QPATH];
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3185         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3186                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3187                         break;
3188
3189         if (!item) {
3190                 rtexture_t *dyntexture;
3191                 // check whether its a dynamic texture
3192                 dyntexture = CL_GetDynTexture( basename );
3193                 if (!add && !dyntexture)
3194                         return NULL;
3195                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3196                 memset(item, 0, sizeof(*item));
3197                 strlcpy(item->basename, basename, sizeof(item->basename));
3198                 item->base = dyntexture; // either NULL or dyntexture handle
3199                 item->textureflags = textureflags;
3200                 item->comparewidth = comparewidth;
3201                 item->compareheight = compareheight;
3202                 item->comparecrc = comparecrc;
3203                 item->next = r_skinframe.hash[hashindex];
3204                 r_skinframe.hash[hashindex] = item;
3205         }
3206         else if( item->base == NULL )
3207         {
3208                 rtexture_t *dyntexture;
3209                 // check whether its a dynamic texture
3210                 // 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]
3211                 dyntexture = CL_GetDynTexture( basename );
3212                 item->base = dyntexture; // either NULL or dyntexture handle
3213         }
3214
3215         R_SkinFrame_MarkUsed(item);
3216         return item;
3217 }
3218
3219 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3220         { \
3221                 unsigned long long avgcolor[5], wsum; \
3222                 int pix, comp, w; \
3223                 avgcolor[0] = 0; \
3224                 avgcolor[1] = 0; \
3225                 avgcolor[2] = 0; \
3226                 avgcolor[3] = 0; \
3227                 avgcolor[4] = 0; \
3228                 wsum = 0; \
3229                 for(pix = 0; pix < cnt; ++pix) \
3230                 { \
3231                         w = 0; \
3232                         for(comp = 0; comp < 3; ++comp) \
3233                                 w += getpixel; \
3234                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3235                         { \
3236                                 ++wsum; \
3237                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3238                                 w = getpixel; \
3239                                 for(comp = 0; comp < 3; ++comp) \
3240                                         avgcolor[comp] += getpixel * w; \
3241                                 avgcolor[3] += w; \
3242                         } \
3243                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3244                         avgcolor[4] += getpixel; \
3245                 } \
3246                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3247                         avgcolor[3] = 1; \
3248                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3249                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3250                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3251                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3252         }
3253
3254 extern cvar_t gl_picmip;
3255 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3256 {
3257         int j;
3258         unsigned char *pixels;
3259         unsigned char *bumppixels;
3260         unsigned char *basepixels = NULL;
3261         int basepixels_width = 0;
3262         int basepixels_height = 0;
3263         skinframe_t *skinframe;
3264         rtexture_t *ddsbase = NULL;
3265         qboolean ddshasalpha = false;
3266         float ddsavgcolor[4];
3267         char basename[MAX_QPATH];
3268         int miplevel = R_PicmipForFlags(textureflags);
3269         int savemiplevel = miplevel;
3270         int mymiplevel;
3271
3272         if (cls.state == ca_dedicated)
3273                 return NULL;
3274
3275         // return an existing skinframe if already loaded
3276         // if loading of the first image fails, don't make a new skinframe as it
3277         // would cause all future lookups of this to be missing
3278         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3279         if (skinframe && skinframe->base)
3280                 return skinframe;
3281
3282         Image_StripImageExtension(name, basename, sizeof(basename));
3283
3284         // check for DDS texture file first
3285         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3286         {
3287                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3288                 if (basepixels == NULL)
3289                         return NULL;
3290         }
3291
3292         // FIXME handle miplevel
3293
3294         if (developer_loading.integer)
3295                 Con_Printf("loading skin \"%s\"\n", name);
3296
3297         // we've got some pixels to store, so really allocate this new texture now
3298         if (!skinframe)
3299                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3300         skinframe->stain = NULL;
3301         skinframe->merged = NULL;
3302         skinframe->base = NULL;
3303         skinframe->pants = NULL;
3304         skinframe->shirt = NULL;
3305         skinframe->nmap = NULL;
3306         skinframe->gloss = NULL;
3307         skinframe->glow = NULL;
3308         skinframe->fog = NULL;
3309         skinframe->reflect = NULL;
3310         skinframe->hasalpha = false;
3311
3312         if (ddsbase)
3313         {
3314                 skinframe->base = ddsbase;
3315                 skinframe->hasalpha = ddshasalpha;
3316                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3317                 if (r_loadfog && skinframe->hasalpha)
3318                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3319                 //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]);
3320         }
3321         else
3322         {
3323                 basepixels_width = image_width;
3324                 basepixels_height = image_height;
3325                 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);
3326                 if (textureflags & TEXF_ALPHA)
3327                 {
3328                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3329                         {
3330                                 if (basepixels[j] < 255)
3331                                 {
3332                                         skinframe->hasalpha = true;
3333                                         break;
3334                                 }
3335                         }
3336                         if (r_loadfog && skinframe->hasalpha)
3337                         {
3338                                 // has transparent pixels
3339                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3340                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3341                                 {
3342                                         pixels[j+0] = 255;
3343                                         pixels[j+1] = 255;
3344                                         pixels[j+2] = 255;
3345                                         pixels[j+3] = basepixels[j+3];
3346                                 }
3347                                 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);
3348                                 Mem_Free(pixels);
3349                         }
3350                 }
3351                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3352 #ifndef USE_GLES2
3353                 //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]);
3354                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3355                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3356                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3357                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3358 #endif
3359         }
3360
3361         if (r_loaddds)
3362         {
3363                 mymiplevel = savemiplevel;
3364                 if (r_loadnormalmap)
3365                         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);
3366                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3367                 if (r_loadgloss)
3368                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3369                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3372         }
3373
3374         // _norm is the name used by tenebrae and has been adopted as standard
3375         if (r_loadnormalmap && skinframe->nmap == NULL)
3376         {
3377                 mymiplevel = savemiplevel;
3378                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3379                 {
3380                         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);
3381                         Mem_Free(pixels);
3382                         pixels = NULL;
3383                 }
3384                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3385                 {
3386                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3387                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3388                         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);
3389                         Mem_Free(pixels);
3390                         Mem_Free(bumppixels);
3391                 }
3392                 else if (r_shadow_bumpscale_basetexture.value > 0)
3393                 {
3394                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3395                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3396                         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);
3397                         Mem_Free(pixels);
3398                 }
3399 #ifndef USE_GLES2
3400                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3401                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3402 #endif
3403         }
3404
3405         // _luma is supported only for tenebrae compatibility
3406         // _glow is the preferred name
3407         mymiplevel = savemiplevel;
3408         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))))
3409         {
3410                 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);
3411 #ifndef USE_GLES2
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3413                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415                 Mem_Free(pixels);pixels = NULL;
3416         }
3417
3418         mymiplevel = savemiplevel;
3419         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3420         {
3421                 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);
3422 #ifndef USE_GLES2
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3424                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3425 #endif
3426                 Mem_Free(pixels);
3427                 pixels = NULL;
3428         }
3429
3430         mymiplevel = savemiplevel;
3431         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3432         {
3433                 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);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3436                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3437 #endif
3438                 Mem_Free(pixels);
3439                 pixels = NULL;
3440         }
3441
3442         mymiplevel = savemiplevel;
3443         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3444         {
3445                 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);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3448                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3449 #endif
3450                 Mem_Free(pixels);
3451                 pixels = NULL;
3452         }
3453
3454         mymiplevel = savemiplevel;
3455         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3456         {
3457                 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);
3458 #ifndef USE_GLES2
3459                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3460                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3461 #endif
3462                 Mem_Free(pixels);
3463                 pixels = NULL;
3464         }
3465
3466         if (basepixels)
3467                 Mem_Free(basepixels);
3468
3469         return skinframe;
3470 }
3471
3472 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3473 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3474 {
3475         int i;
3476         unsigned char *temp1, *temp2;
3477         skinframe_t *skinframe;
3478
3479         if (cls.state == ca_dedicated)
3480                 return NULL;
3481
3482         // if already loaded just return it, otherwise make a new skinframe
3483         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3484         if (skinframe && skinframe->base)
3485                 return skinframe;
3486
3487         skinframe->stain = NULL;
3488         skinframe->merged = NULL;
3489         skinframe->base = NULL;
3490         skinframe->pants = NULL;
3491         skinframe->shirt = NULL;
3492         skinframe->nmap = NULL;
3493         skinframe->gloss = NULL;
3494         skinframe->glow = NULL;
3495         skinframe->fog = NULL;
3496         skinframe->reflect = NULL;
3497         skinframe->hasalpha = false;
3498
3499         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3500         if (!skindata)
3501                 return NULL;
3502
3503         if (developer_loading.integer)
3504                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3505
3506         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3507         {
3508                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3509                 temp2 = temp1 + width * height * 4;
3510                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3511                 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);
3512                 Mem_Free(temp1);
3513         }
3514         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3515         if (textureflags & TEXF_ALPHA)
3516         {
3517                 for (i = 3;i < width * height * 4;i += 4)
3518                 {
3519                         if (skindata[i] < 255)
3520                         {
3521                                 skinframe->hasalpha = true;
3522                                 break;
3523                         }
3524                 }
3525                 if (r_loadfog && skinframe->hasalpha)
3526                 {
3527                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3528                         memcpy(fogpixels, skindata, width * height * 4);
3529                         for (i = 0;i < width * height * 4;i += 4)
3530                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3531                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3532                         Mem_Free(fogpixels);
3533                 }
3534         }
3535
3536         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3537         //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]);
3538
3539         return skinframe;
3540 }
3541
3542 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3543 {
3544         int i;
3545         int featuresmask;
3546         skinframe_t *skinframe;
3547
3548         if (cls.state == ca_dedicated)
3549                 return NULL;
3550
3551         // if already loaded just return it, otherwise make a new skinframe
3552         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3553         if (skinframe && skinframe->base)
3554                 return skinframe;
3555
3556         skinframe->stain = NULL;
3557         skinframe->merged = NULL;
3558         skinframe->base = NULL;
3559         skinframe->pants = NULL;
3560         skinframe->shirt = NULL;
3561         skinframe->nmap = NULL;
3562         skinframe->gloss = NULL;
3563         skinframe->glow = NULL;
3564         skinframe->fog = NULL;
3565         skinframe->reflect = NULL;
3566         skinframe->hasalpha = false;
3567
3568         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3569         if (!skindata)
3570                 return NULL;
3571
3572         if (developer_loading.integer)
3573                 Con_Printf("loading quake skin \"%s\"\n", name);
3574
3575         // 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)
3576         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3577         memcpy(skinframe->qpixels, skindata, width*height);
3578         skinframe->qwidth = width;
3579         skinframe->qheight = height;
3580
3581         featuresmask = 0;
3582         for (i = 0;i < width * height;i++)
3583                 featuresmask |= palette_featureflags[skindata[i]];
3584
3585         skinframe->hasalpha = false;
3586         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3587         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3588         skinframe->qgeneratemerged = true;
3589         skinframe->qgeneratebase = skinframe->qhascolormapping;
3590         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3591
3592         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3593         //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]);
3594
3595         return skinframe;
3596 }
3597
3598 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3599 {
3600         int width;
3601         int height;
3602         unsigned char *skindata;
3603
3604         if (!skinframe->qpixels)
3605                 return;
3606
3607         if (!skinframe->qhascolormapping)
3608                 colormapped = false;
3609
3610         if (colormapped)
3611         {
3612                 if (!skinframe->qgeneratebase)
3613                         return;
3614         }
3615         else
3616         {
3617                 if (!skinframe->qgeneratemerged)
3618                         return;
3619         }
3620
3621         width = skinframe->qwidth;
3622         height = skinframe->qheight;
3623         skindata = skinframe->qpixels;
3624
3625         if (skinframe->qgeneratenmap)
3626         {
3627                 unsigned char *temp1, *temp2;
3628                 skinframe->qgeneratenmap = false;
3629                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3630                 temp2 = temp1 + width * height * 4;
3631                 // use either a custom palette or the quake palette
3632                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3633                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3634                 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);
3635                 Mem_Free(temp1);
3636         }
3637
3638         if (skinframe->qgenerateglow)
3639         {
3640                 skinframe->qgenerateglow = false;
3641                 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
3642         }
3643
3644         if (colormapped)
3645         {
3646                 skinframe->qgeneratebase = false;
3647                 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);
3648                 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);
3649                 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);
3650         }
3651         else
3652         {
3653                 skinframe->qgeneratemerged = false;
3654                 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);
3655         }
3656
3657         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3658         {
3659                 Mem_Free(skinframe->qpixels);
3660                 skinframe->qpixels = NULL;
3661         }
3662 }
3663
3664 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)
3665 {
3666         int i;
3667         skinframe_t *skinframe;
3668
3669         if (cls.state == ca_dedicated)
3670                 return NULL;
3671
3672         // if already loaded just return it, otherwise make a new skinframe
3673         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3674         if (skinframe && skinframe->base)
3675                 return skinframe;
3676
3677         skinframe->stain = NULL;
3678         skinframe->merged = NULL;
3679         skinframe->base = NULL;
3680         skinframe->pants = NULL;
3681         skinframe->shirt = NULL;
3682         skinframe->nmap = NULL;
3683         skinframe->gloss = NULL;
3684         skinframe->glow = NULL;
3685         skinframe->fog = NULL;
3686         skinframe->reflect = NULL;
3687         skinframe->hasalpha = false;
3688
3689         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3690         if (!skindata)
3691                 return NULL;
3692
3693         if (developer_loading.integer)
3694                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3695
3696         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3697         if (textureflags & TEXF_ALPHA)
3698         {
3699                 for (i = 0;i < width * height;i++)
3700                 {
3701                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3702                         {
3703                                 skinframe->hasalpha = true;
3704                                 break;
3705                         }
3706                 }
3707                 if (r_loadfog && skinframe->hasalpha)
3708                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3709         }
3710
3711         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3712         //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]);
3713
3714         return skinframe;
3715 }
3716
3717 skinframe_t *R_SkinFrame_LoadMissing(void)
3718 {
3719         skinframe_t *skinframe;
3720
3721         if (cls.state == ca_dedicated)
3722                 return NULL;
3723
3724         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3725         skinframe->stain = NULL;
3726         skinframe->merged = NULL;
3727         skinframe->base = NULL;
3728         skinframe->pants = NULL;
3729         skinframe->shirt = NULL;
3730         skinframe->nmap = NULL;
3731         skinframe->gloss = NULL;
3732         skinframe->glow = NULL;
3733         skinframe->fog = NULL;
3734         skinframe->reflect = NULL;
3735         skinframe->hasalpha = false;
3736
3737         skinframe->avgcolor[0] = rand() / RAND_MAX;
3738         skinframe->avgcolor[1] = rand() / RAND_MAX;
3739         skinframe->avgcolor[2] = rand() / RAND_MAX;
3740         skinframe->avgcolor[3] = 1;
3741
3742         return skinframe;
3743 }
3744
3745 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3746 typedef struct suffixinfo_s
3747 {
3748         const char *suffix;
3749         qboolean flipx, flipy, flipdiagonal;
3750 }
3751 suffixinfo_t;
3752 static suffixinfo_t suffix[3][6] =
3753 {
3754         {
3755                 {"px",   false, false, false},
3756                 {"nx",   false, false, false},
3757                 {"py",   false, false, false},
3758                 {"ny",   false, false, false},
3759                 {"pz",   false, false, false},
3760                 {"nz",   false, false, false}
3761         },
3762         {
3763                 {"posx", false, false, false},
3764                 {"negx", false, false, false},
3765                 {"posy", false, false, false},
3766                 {"negy", false, false, false},
3767                 {"posz", false, false, false},
3768                 {"negz", false, false, false}
3769         },
3770         {
3771                 {"rt",    true, false,  true},
3772                 {"lf",   false,  true,  true},
3773                 {"ft",    true,  true, false},
3774                 {"bk",   false, false, false},
3775                 {"up",    true, false,  true},
3776                 {"dn",    true, false,  true}
3777         }
3778 };
3779
3780 static int componentorder[4] = {0, 1, 2, 3};
3781
3782 rtexture_t *R_LoadCubemap(const char *basename)
3783 {
3784         int i, j, cubemapsize;
3785         unsigned char *cubemappixels, *image_buffer;
3786         rtexture_t *cubemaptexture;
3787         char name[256];
3788         // must start 0 so the first loadimagepixels has no requested width/height
3789         cubemapsize = 0;
3790         cubemappixels = NULL;
3791         cubemaptexture = NULL;
3792         // keep trying different suffix groups (posx, px, rt) until one loads
3793         for (j = 0;j < 3 && !cubemappixels;j++)
3794         {
3795                 // load the 6 images in the suffix group
3796                 for (i = 0;i < 6;i++)
3797                 {
3798                         // generate an image name based on the base and and suffix
3799                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3800                         // load it
3801                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3802                         {
3803                                 // an image loaded, make sure width and height are equal
3804                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3805                                 {
3806                                         // if this is the first image to load successfully, allocate the cubemap memory
3807                                         if (!cubemappixels && image_width >= 1)
3808                                         {
3809                                                 cubemapsize = image_width;
3810                                                 // note this clears to black, so unavailable sides are black
3811                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3812                                         }
3813                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3814                                         if (cubemappixels)
3815                                                 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);
3816                                 }
3817                                 else
3818                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3819                                 // free the image
3820                                 Mem_Free(image_buffer);
3821                         }
3822                 }
3823         }
3824         // if a cubemap loaded, upload it
3825         if (cubemappixels)
3826         {
3827                 if (developer_loading.integer)
3828                         Con_Printf("loading cubemap \"%s\"\n", basename);
3829
3830                 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);
3831                 Mem_Free(cubemappixels);
3832         }
3833         else
3834         {
3835                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3836                 if (developer_loading.integer)
3837                 {
3838                         Con_Printf("(tried tried images ");
3839                         for (j = 0;j < 3;j++)
3840                                 for (i = 0;i < 6;i++)
3841                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3842                         Con_Print(" and was unable to find any of them).\n");
3843                 }
3844         }
3845         return cubemaptexture;
3846 }
3847
3848 rtexture_t *R_GetCubemap(const char *basename)
3849 {
3850         int i;
3851         for (i = 0;i < r_texture_numcubemaps;i++)
3852                 if (r_texture_cubemaps[i] != NULL)
3853                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3854                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3855         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3856                 return r_texture_whitecube;
3857         r_texture_numcubemaps++;
3858         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3859         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3860         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3861         return r_texture_cubemaps[i]->texture;
3862 }
3863
3864 void R_FreeCubemap(const char *basename)
3865 {
3866         int i;
3867
3868         for (i = 0;i < r_texture_numcubemaps;i++)
3869         {
3870                 if (r_texture_cubemaps[i] != NULL)
3871                 {
3872                         if (r_texture_cubemaps[i]->texture)
3873                         {
3874                                 if (developer_loading.integer)
3875                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3876                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3877                                 Mem_Free(r_texture_cubemaps[i]);
3878                                 r_texture_cubemaps[i] = NULL;
3879                         }
3880                 }
3881         }
3882 }
3883
3884 void R_FreeCubemaps(void)
3885 {
3886         int i;
3887         for (i = 0;i < r_texture_numcubemaps;i++)
3888         {
3889                 if (developer_loading.integer)
3890                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3891                 if (r_texture_cubemaps[i] != NULL)
3892                 {
3893                         if (r_texture_cubemaps[i]->texture)
3894                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3895                         Mem_Free(r_texture_cubemaps[i]);
3896                 }
3897         }
3898         r_texture_numcubemaps = 0;
3899 }
3900
3901 void R_Main_FreeViewCache(void)
3902 {
3903         if (r_refdef.viewcache.entityvisible)
3904                 Mem_Free(r_refdef.viewcache.entityvisible);
3905         if (r_refdef.viewcache.world_pvsbits)
3906                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3907         if (r_refdef.viewcache.world_leafvisible)
3908                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3909         if (r_refdef.viewcache.world_surfacevisible)
3910                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3911         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3912 }
3913
3914 void R_Main_ResizeViewCache(void)
3915 {
3916         int numentities = r_refdef.scene.numentities;
3917         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3918         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3919         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3920         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3921         if (r_refdef.viewcache.maxentities < numentities)
3922         {
3923                 r_refdef.viewcache.maxentities = numentities;
3924                 if (r_refdef.viewcache.entityvisible)
3925                         Mem_Free(r_refdef.viewcache.entityvisible);
3926                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3927         }
3928         if (r_refdef.viewcache.world_numclusters != numclusters)
3929         {
3930                 r_refdef.viewcache.world_numclusters = numclusters;
3931                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3932                 if (r_refdef.viewcache.world_pvsbits)
3933                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3934                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3935         }
3936         if (r_refdef.viewcache.world_numleafs != numleafs)
3937         {
3938                 r_refdef.viewcache.world_numleafs = numleafs;
3939                 if (r_refdef.viewcache.world_leafvisible)
3940                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3941                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3942         }
3943         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3944         {
3945                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3946                 if (r_refdef.viewcache.world_surfacevisible)
3947                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3948                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3949         }
3950 }
3951
3952 extern rtexture_t *loadingscreentexture;
3953 void gl_main_start(void)
3954 {
3955         loadingscreentexture = NULL;
3956         r_texture_blanknormalmap = NULL;
3957         r_texture_white = NULL;
3958         r_texture_grey128 = NULL;
3959         r_texture_black = NULL;
3960         r_texture_whitecube = NULL;
3961         r_texture_normalizationcube = NULL;
3962         r_texture_fogattenuation = NULL;
3963         r_texture_fogheighttexture = NULL;
3964         r_texture_gammaramps = NULL;
3965         r_texture_numcubemaps = 0;
3966
3967         r_loaddds = r_texture_dds_load.integer != 0;
3968         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3969
3970         switch(vid.renderpath)
3971         {
3972         case RENDERPATH_GL20:
3973         case RENDERPATH_D3D9:
3974         case RENDERPATH_D3D10:
3975         case RENDERPATH_D3D11:
3976         case RENDERPATH_SOFT:
3977         case RENDERPATH_GLES2:
3978                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3979                 Cvar_SetValueQuick(&gl_combine, 1);
3980                 Cvar_SetValueQuick(&r_glsl, 1);
3981                 r_loadnormalmap = true;
3982                 r_loadgloss = true;
3983                 r_loadfog = false;
3984                 break;
3985         case RENDERPATH_GL13:
3986         case RENDERPATH_GLES1:
3987                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3988                 Cvar_SetValueQuick(&gl_combine, 1);
3989                 Cvar_SetValueQuick(&r_glsl, 0);
3990                 r_loadnormalmap = false;
3991                 r_loadgloss = false;
3992                 r_loadfog = true;
3993                 break;
3994         case RENDERPATH_GL11:
3995                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3996                 Cvar_SetValueQuick(&gl_combine, 0);
3997                 Cvar_SetValueQuick(&r_glsl, 0);
3998                 r_loadnormalmap = false;
3999                 r_loadgloss = false;
4000                 r_loadfog = true;
4001                 break;
4002         }
4003
4004         R_AnimCache_Free();
4005         R_FrameData_Reset();
4006
4007         r_numqueries = 0;
4008         r_maxqueries = 0;
4009         memset(r_queries, 0, sizeof(r_queries));
4010
4011         r_qwskincache = NULL;
4012         r_qwskincache_size = 0;
4013
4014         // due to caching of texture_t references, the collision cache must be reset
4015         Collision_Cache_Reset(true);
4016
4017         // set up r_skinframe loading system for textures
4018         memset(&r_skinframe, 0, sizeof(r_skinframe));
4019         r_skinframe.loadsequence = 1;
4020         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4021
4022         r_main_texturepool = R_AllocTexturePool();
4023         R_BuildBlankTextures();
4024         R_BuildNoTexture();
4025         if (vid.support.arb_texture_cube_map)
4026         {
4027                 R_BuildWhiteCube();
4028                 R_BuildNormalizationCube();
4029         }
4030         r_texture_fogattenuation = NULL;
4031         r_texture_fogheighttexture = NULL;
4032         r_texture_gammaramps = NULL;
4033         //r_texture_fogintensity = NULL;
4034         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4035         memset(&r_waterstate, 0, sizeof(r_waterstate));
4036         r_glsl_permutation = NULL;
4037         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4038         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4039         glslshaderstring = NULL;
4040 #ifdef SUPPORTD3D
4041         r_hlsl_permutation = NULL;
4042         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4043         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4044 #endif
4045         hlslshaderstring = NULL;
4046         memset(&r_svbsp, 0, sizeof (r_svbsp));
4047
4048         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4049         r_texture_numcubemaps = 0;
4050
4051         r_refdef.fogmasktable_density = 0;
4052 }
4053
4054 void gl_main_shutdown(void)
4055 {
4056         R_AnimCache_Free();
4057         R_FrameData_Reset();
4058
4059         R_Main_FreeViewCache();
4060
4061         switch(vid.renderpath)
4062         {
4063         case RENDERPATH_GL11:
4064         case RENDERPATH_GL13:
4065         case RENDERPATH_GL20:
4066         case RENDERPATH_GLES1:
4067         case RENDERPATH_GLES2:
4068 #ifdef GL_SAMPLES_PASSED_ARB
4069                 if (r_maxqueries)
4070                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4071 #endif
4072                 break;
4073         case RENDERPATH_D3D9:
4074                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075                 break;
4076         case RENDERPATH_D3D10:
4077                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4078                 break;
4079         case RENDERPATH_D3D11:
4080                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4081                 break;
4082         case RENDERPATH_SOFT:
4083                 break;
4084         }
4085
4086         r_numqueries = 0;
4087         r_maxqueries = 0;
4088         memset(r_queries, 0, sizeof(r_queries));
4089
4090         r_qwskincache = NULL;
4091         r_qwskincache_size = 0;
4092
4093         // clear out the r_skinframe state
4094         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4095         memset(&r_skinframe, 0, sizeof(r_skinframe));
4096
4097         if (r_svbsp.nodes)
4098                 Mem_Free(r_svbsp.nodes);
4099         memset(&r_svbsp, 0, sizeof (r_svbsp));
4100         R_FreeTexturePool(&r_main_texturepool);
4101         loadingscreentexture = NULL;
4102         r_texture_blanknormalmap = NULL;
4103         r_texture_white = NULL;
4104         r_texture_grey128 = NULL;
4105         r_texture_black = NULL;
4106         r_texture_whitecube = NULL;
4107         r_texture_normalizationcube = NULL;
4108         r_texture_fogattenuation = NULL;
4109         r_texture_fogheighttexture = NULL;
4110         r_texture_gammaramps = NULL;
4111         r_texture_numcubemaps = 0;
4112         //r_texture_fogintensity = NULL;
4113         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4114         memset(&r_waterstate, 0, sizeof(r_waterstate));
4115         R_GLSL_Restart_f();
4116
4117         r_glsl_permutation = NULL;
4118         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4119         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4120         glslshaderstring = NULL;
4121 #ifdef SUPPORTD3D
4122         r_hlsl_permutation = NULL;
4123         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4124         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4125 #endif
4126         hlslshaderstring = NULL;
4127 }
4128
4129 extern void CL_ParseEntityLump(char *entitystring);
4130 void gl_main_newmap(void)
4131 {
4132         // FIXME: move this code to client
4133         char *entities, entname[MAX_QPATH];
4134         if (r_qwskincache)
4135                 Mem_Free(r_qwskincache);
4136         r_qwskincache = NULL;
4137         r_qwskincache_size = 0;
4138         if (cl.worldmodel)
4139         {
4140                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4141                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4142                 {
4143                         CL_ParseEntityLump(entities);
4144                         Mem_Free(entities);
4145                         return;
4146                 }
4147                 if (cl.worldmodel->brush.entities)
4148                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4149         }
4150         R_Main_FreeViewCache();
4151
4152         R_FrameData_Reset();
4153 }
4154
4155 void GL_Main_Init(void)
4156 {
4157         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4158
4159         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4160         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4161         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4162         if (gamemode == GAME_NEHAHRA)
4163         {
4164                 Cvar_RegisterVariable (&gl_fogenable);
4165                 Cvar_RegisterVariable (&gl_fogdensity);
4166                 Cvar_RegisterVariable (&gl_fogred);
4167                 Cvar_RegisterVariable (&gl_foggreen);
4168                 Cvar_RegisterVariable (&gl_fogblue);
4169                 Cvar_RegisterVariable (&gl_fogstart);
4170                 Cvar_RegisterVariable (&gl_fogend);
4171                 Cvar_RegisterVariable (&gl_skyclip);
4172         }
4173         Cvar_RegisterVariable(&r_motionblur);
4174         Cvar_RegisterVariable(&r_damageblur);
4175         Cvar_RegisterVariable(&r_motionblur_averaging);
4176         Cvar_RegisterVariable(&r_motionblur_randomize);
4177         Cvar_RegisterVariable(&r_motionblur_minblur);
4178         Cvar_RegisterVariable(&r_motionblur_maxblur);
4179         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4180         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4181         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4182         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4183         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4184         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4185         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4186         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4187         Cvar_RegisterVariable(&r_equalize_entities_by);
4188         Cvar_RegisterVariable(&r_equalize_entities_to);
4189         Cvar_RegisterVariable(&r_depthfirst);
4190         Cvar_RegisterVariable(&r_useinfinitefarclip);
4191         Cvar_RegisterVariable(&r_farclip_base);
4192         Cvar_RegisterVariable(&r_farclip_world);
4193         Cvar_RegisterVariable(&r_nearclip);
4194         Cvar_RegisterVariable(&r_deformvertexes);
4195         Cvar_RegisterVariable(&r_transparent);
4196         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4197         Cvar_RegisterVariable(&r_showoverdraw);
4198         Cvar_RegisterVariable(&r_showbboxes);
4199         Cvar_RegisterVariable(&r_showsurfaces);
4200         Cvar_RegisterVariable(&r_showtris);
4201         Cvar_RegisterVariable(&r_shownormals);
4202         Cvar_RegisterVariable(&r_showlighting);
4203         Cvar_RegisterVariable(&r_showshadowvolumes);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes);
4205         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4206         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4207         Cvar_RegisterVariable(&r_showdisabledepthtest);
4208         Cvar_RegisterVariable(&r_drawportals);
4209         Cvar_RegisterVariable(&r_drawentities);
4210         Cvar_RegisterVariable(&r_draw2d);
4211         Cvar_RegisterVariable(&r_drawworld);
4212         Cvar_RegisterVariable(&r_cullentities_trace);
4213         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4214         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4215         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4216         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4217         Cvar_RegisterVariable(&r_sortentities);
4218         Cvar_RegisterVariable(&r_drawviewmodel);
4219         Cvar_RegisterVariable(&r_drawexteriormodel);
4220         Cvar_RegisterVariable(&r_speeds);
4221         Cvar_RegisterVariable(&r_fullbrights);
4222         Cvar_RegisterVariable(&r_wateralpha);
4223         Cvar_RegisterVariable(&r_dynamic);
4224         Cvar_RegisterVariable(&r_fakelight);
4225         Cvar_RegisterVariable(&r_fakelight_intensity);
4226         Cvar_RegisterVariable(&r_fullbright);
4227         Cvar_RegisterVariable(&r_shadows);
4228         Cvar_RegisterVariable(&r_shadows_darken);
4229         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4230         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4231         Cvar_RegisterVariable(&r_shadows_throwdistance);
4232         Cvar_RegisterVariable(&r_shadows_throwdirection);
4233         Cvar_RegisterVariable(&r_shadows_focus);
4234         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4235         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4236         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4237         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4238         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4239         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4240         Cvar_RegisterVariable(&r_fog_exp2);
4241         Cvar_RegisterVariable(&r_fog_clear);
4242         Cvar_RegisterVariable(&r_drawfog);
4243         Cvar_RegisterVariable(&r_transparentdepthmasking);
4244         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4245         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4246         Cvar_RegisterVariable(&r_texture_dds_load);
4247         Cvar_RegisterVariable(&r_texture_dds_save);
4248         Cvar_RegisterVariable(&r_textureunits);
4249         Cvar_RegisterVariable(&gl_combine);
4250         Cvar_RegisterVariable(&r_viewfbo);
4251         Cvar_RegisterVariable(&r_viewscale);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4258         Cvar_RegisterVariable(&r_glsl);
4259         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4266         Cvar_RegisterVariable(&r_glsl_postprocess);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4275
4276         Cvar_RegisterVariable(&r_water);
4277         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4278         Cvar_RegisterVariable(&r_water_clippingplanebias);
4279         Cvar_RegisterVariable(&r_water_refractdistort);
4280         Cvar_RegisterVariable(&r_water_reflectdistort);
4281         Cvar_RegisterVariable(&r_water_scissormode);
4282         Cvar_RegisterVariable(&r_water_lowquality);
4283
4284         Cvar_RegisterVariable(&r_lerpsprites);
4285         Cvar_RegisterVariable(&r_lerpmodels);
4286         Cvar_RegisterVariable(&r_lerplightstyles);
4287         Cvar_RegisterVariable(&r_waterscroll);
4288         Cvar_RegisterVariable(&r_bloom);
4289         Cvar_RegisterVariable(&r_bloom_colorscale);
4290         Cvar_RegisterVariable(&r_bloom_brighten);
4291         Cvar_RegisterVariable(&r_bloom_blur);
4292         Cvar_RegisterVariable(&r_bloom_resolution);
4293         Cvar_RegisterVariable(&r_bloom_colorexponent);
4294         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4295         Cvar_RegisterVariable(&r_hdr);
4296         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4297         Cvar_RegisterVariable(&r_hdr_glowintensity);
4298         Cvar_RegisterVariable(&r_hdr_range);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4300         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4306         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4307         Cvar_RegisterVariable(&developer_texturelogging);
4308         Cvar_RegisterVariable(&gl_lightmaps);
4309         Cvar_RegisterVariable(&r_test);
4310         Cvar_RegisterVariable(&r_glsl_saturation);
4311         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4312         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4313         Cvar_RegisterVariable(&r_framedatasize);
4314         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4315                 Cvar_SetValue("r_fullbrights", 0);
4316         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4317 }
4318
4319 extern void R_Textures_Init(void);
4320 extern void GL_Draw_Init(void);
4321 extern void GL_Main_Init(void);
4322 extern void R_Shadow_Init(void);
4323 extern void R_Sky_Init(void);
4324 extern void GL_Surf_Init(void);
4325 extern void R_Particles_Init(void);
4326 extern void R_Explosion_Init(void);
4327 extern void gl_backend_init(void);
4328 extern void Sbar_Init(void);
4329 extern void R_LightningBeams_Init(void);
4330 extern void Mod_RenderInit(void);
4331 extern void Font_Init(void);
4332
4333 void Render_Init(void)
4334 {
4335         gl_backend_init();
4336         R_Textures_Init();
4337         GL_Main_Init();
4338         Font_Init();
4339         GL_Draw_Init();
4340         R_Shadow_Init();
4341         R_Sky_Init();
4342         GL_Surf_Init();
4343         Sbar_Init();
4344         R_Particles_Init();
4345         R_Explosion_Init();
4346         R_LightningBeams_Init();
4347         Mod_RenderInit();
4348 }
4349
4350 /*
4351 ===============
4352 GL_Init
4353 ===============
4354 */
4355 #ifndef USE_GLES2
4356 extern char *ENGINE_EXTENSIONS;
4357 void GL_Init (void)
4358 {
4359         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4360         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4361         gl_version = (const char *)qglGetString(GL_VERSION);
4362         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4363
4364         if (!gl_extensions)
4365                 gl_extensions = "";
4366         if (!gl_platformextensions)
4367                 gl_platformextensions = "";
4368
4369         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4370         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4371         Con_Printf("GL_VERSION: %s\n", gl_version);
4372         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4373         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4374
4375         VID_CheckExtensions();
4376
4377         // LordHavoc: report supported extensions
4378         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4379
4380         // clear to black (loading plaque will be seen over this)
4381         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4382 }
4383 #endif
4384
4385 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4386 {
4387         int i;
4388         mplane_t *p;
4389         if (r_trippy.integer)
4390                 return false;
4391         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4392         {
4393                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4394                 if (i == 4)
4395                         continue;
4396                 p = r_refdef.view.frustum + i;
4397                 switch(p->signbits)
4398                 {
4399                 default:
4400                 case 0:
4401                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 1:
4405                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 2:
4409                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 case 3:
4413                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4414                                 return true;
4415                         break;
4416                 case 4:
4417                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4418                                 return true;
4419                         break;
4420                 case 5:
4421                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4422                                 return true;
4423                         break;
4424                 case 6:
4425                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4426                                 return true;
4427                         break;
4428                 case 7:
4429                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4430                                 return true;
4431                         break;
4432                 }
4433         }
4434         return false;
4435 }
4436
4437 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4438 {
4439         int i;
4440         const mplane_t *p;
4441         if (r_trippy.integer)
4442                 return false;
4443         for (i = 0;i < numplanes;i++)
4444         {
4445                 p = planes + i;
4446                 switch(p->signbits)
4447                 {
4448                 default:
4449                 case 0:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 1:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 2:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 3:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 case 4:
4466                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4467                                 return true;
4468                         break;
4469                 case 5:
4470                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4471                                 return true;
4472                         break;
4473                 case 6:
4474                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4475                                 return true;
4476                         break;
4477                 case 7:
4478                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4479                                 return true;
4480                         break;
4481                 }
4482         }
4483         return false;
4484 }
4485
4486 //==================================================================================
4487
4488 // LordHavoc: this stores temporary data used within the same frame
4489
4490 typedef struct r_framedata_mem_s
4491 {
4492         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4493         size_t size; // how much usable space
4494         size_t current; // how much space in use
4495         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4496         size_t wantedsize; // how much space was allocated
4497         unsigned char *data; // start of real data (16byte aligned)
4498 }
4499 r_framedata_mem_t;
4500
4501 static r_framedata_mem_t *r_framedata_mem;
4502
4503 void R_FrameData_Reset(void)
4504 {
4505         while (r_framedata_mem)
4506         {
4507                 r_framedata_mem_t *next = r_framedata_mem->purge;
4508                 Mem_Free(r_framedata_mem);
4509                 r_framedata_mem = next;
4510         }
4511 }
4512
4513 void R_FrameData_Resize(void)
4514 {
4515         size_t wantedsize;
4516         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4517         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4518         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4519         {
4520                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4521                 newmem->wantedsize = wantedsize;
4522                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4523                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4524                 newmem->current = 0;
4525                 newmem->mark = 0;
4526                 newmem->purge = r_framedata_mem;
4527                 r_framedata_mem = newmem;
4528         }
4529 }
4530
4531 void R_FrameData_NewFrame(void)
4532 {
4533         R_FrameData_Resize();
4534         if (!r_framedata_mem)
4535                 return;
4536         // if we ran out of space on the last frame, free the old memory now
4537         while (r_framedata_mem->purge)
4538         {
4539                 // repeatedly remove the second item in the list, leaving only head
4540                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4541                 Mem_Free(r_framedata_mem->purge);
4542                 r_framedata_mem->purge = next;
4543         }
4544         // reset the current mem pointer
4545         r_framedata_mem->current = 0;
4546         r_framedata_mem->mark = 0;
4547 }
4548
4549 void *R_FrameData_Alloc(size_t size)
4550 {
4551         void *data;
4552
4553         // align to 16 byte boundary - the data pointer is already aligned, so we
4554         // only need to ensure the size of every allocation is also aligned
4555         size = (size + 15) & ~15;
4556
4557         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4558         {
4559                 // emergency - we ran out of space, allocate more memory
4560                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4561                 R_FrameData_Resize();
4562         }
4563
4564         data = r_framedata_mem->data + r_framedata_mem->current;
4565         r_framedata_mem->current += size;
4566
4567         // count the usage for stats
4568         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4569         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4570
4571         return (void *)data;
4572 }
4573
4574 void *R_FrameData_Store(size_t size, void *data)
4575 {
4576         void *d = R_FrameData_Alloc(size);
4577         if (d && data)
4578                 memcpy(d, data, size);
4579         return d;
4580 }
4581
4582 void R_FrameData_SetMark(void)
4583 {
4584         if (!r_framedata_mem)
4585                 return;
4586         r_framedata_mem->mark = r_framedata_mem->current;
4587 }
4588
4589 void R_FrameData_ReturnToMark(void)
4590 {
4591         if (!r_framedata_mem)
4592                 return;
4593         r_framedata_mem->current = r_framedata_mem->mark;
4594 }
4595
4596 //==================================================================================
4597
4598 // LordHavoc: animcache originally written by Echon, rewritten since then
4599
4600 /**
4601  * Animation cache prevents re-generating mesh data for an animated model
4602  * multiple times in one frame for lighting, shadowing, reflections, etc.
4603  */
4604
4605 void R_AnimCache_Free(void)
4606 {
4607 }
4608
4609 void R_AnimCache_ClearCache(void)
4610 {
4611         int i;
4612         entity_render_t *ent;
4613
4614         for (i = 0;i < r_refdef.scene.numentities;i++)
4615         {
4616                 ent = r_refdef.scene.entities[i];
4617                 ent->animcache_vertex3f = NULL;
4618                 ent->animcache_normal3f = NULL;
4619                 ent->animcache_svector3f = NULL;
4620                 ent->animcache_tvector3f = NULL;
4621                 ent->animcache_vertexmesh = NULL;
4622                 ent->animcache_vertex3fbuffer = NULL;
4623                 ent->animcache_vertexmeshbuffer = NULL;
4624         }
4625 }
4626
4627 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4628 {
4629         int i;
4630
4631         // check if we need the meshbuffers
4632         if (!vid.useinterleavedarrays)
4633                 return;
4634
4635         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4636                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4637         // TODO: upload vertex3f buffer?
4638         if (ent->animcache_vertexmesh)
4639         {
4640                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4641                 for (i = 0;i < numvertices;i++)
4642                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4643                 if (ent->animcache_svector3f)
4644                         for (i = 0;i < numvertices;i++)
4645                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4646                 if (ent->animcache_tvector3f)
4647                         for (i = 0;i < numvertices;i++)
4648                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4649                 if (ent->animcache_normal3f)
4650                         for (i = 0;i < numvertices;i++)
4651                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4652                 // TODO: upload vertexmeshbuffer?
4653         }
4654 }
4655
4656 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4657 {
4658         dp_model_t *model = ent->model;
4659         int numvertices;
4660         // see if it's already cached this frame
4661         if (ent->animcache_vertex3f)
4662         {
4663                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4664                 if (wantnormals || wanttangents)
4665                 {
4666                         if (ent->animcache_normal3f)
4667                                 wantnormals = false;
4668                         if (ent->animcache_svector3f)
4669                                 wanttangents = false;
4670                         if (wantnormals || wanttangents)
4671                         {
4672                                 numvertices = model->surfmesh.num_vertices;
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, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4681                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4682                         }
4683                 }
4684         }
4685         else
4686         {
4687                 // see if this ent is worth caching
4688                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4689                         return false;
4690                 // get some memory for this entity and generate mesh data
4691                 numvertices = model->surfmesh.num_vertices;
4692                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                 if (wantnormals)
4694                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4695                 if (wanttangents)
4696                 {
4697                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4698                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4699                 }
4700                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4701                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4702         }
4703         return true;
4704 }
4705
4706 void R_AnimCache_CacheVisibleEntities(void)
4707 {
4708         int i;
4709         qboolean wantnormals = true;
4710         qboolean wanttangents = !r_showsurfaces.integer;
4711
4712         switch(vid.renderpath)
4713         {
4714         case RENDERPATH_GL20:
4715         case RENDERPATH_D3D9:
4716         case RENDERPATH_D3D10:
4717         case RENDERPATH_D3D11:
4718         case RENDERPATH_GLES2:
4719                 break;
4720         case RENDERPATH_GL11:
4721         case RENDERPATH_GL13:
4722         case RENDERPATH_GLES1:
4723                 wanttangents = false;
4724                 break;
4725         case RENDERPATH_SOFT:
4726                 break;
4727         }
4728
4729         if (r_shownormals.integer)
4730                 wanttangents = wantnormals = true;
4731
4732         // TODO: thread this
4733         // NOTE: R_PrepareRTLights() also caches entities
4734
4735         for (i = 0;i < r_refdef.scene.numentities;i++)
4736                 if (r_refdef.viewcache.entityvisible[i])
4737                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4738 }
4739
4740 //==================================================================================
4741
4742 extern cvar_t r_overheadsprites_pushback;
4743
4744 static void R_View_UpdateEntityLighting (void)
4745 {
4746         int i;
4747         entity_render_t *ent;
4748         vec3_t tempdiffusenormal, avg;
4749         vec_t f, fa, fd, fdd;
4750         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4751
4752         for (i = 0;i < r_refdef.scene.numentities;i++)
4753         {
4754                 ent = r_refdef.scene.entities[i];
4755
4756                 // skip unseen models
4757                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4758                         continue;
4759
4760                 // skip bsp models
4761                 if (ent->model && ent->model->brush.num_leafs)
4762                 {
4763                         // TODO: use modellight for r_ambient settings on world?
4764                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4765                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4766                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4767                         continue;
4768                 }
4769
4770                 // fetch the lighting from the worldmodel data
4771                 VectorClear(ent->modellight_ambient);
4772                 VectorClear(ent->modellight_diffuse);
4773                 VectorClear(tempdiffusenormal);
4774                 if (ent->flags & RENDER_LIGHT)
4775                 {
4776                         vec3_t org;
4777                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4778
4779                         // complete lightning for lit sprites
4780                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4781                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4782                         {
4783                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4784                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4785                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4786                         }
4787                         else
4788                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4789
4790                         if(ent->flags & RENDER_EQUALIZE)
4791                         {
4792                                 // first fix up ambient lighting...
4793                                 if(r_equalize_entities_minambient.value > 0)
4794                                 {
4795                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4796                                         if(fd > 0)
4797                                         {
4798                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4799                                                 if(fa < r_equalize_entities_minambient.value * fd)
4800                                                 {
4801                                                         // solve:
4802                                                         //   fa'/fd' = minambient
4803                                                         //   fa'+0.25*fd' = fa+0.25*fd
4804                                                         //   ...
4805                                                         //   fa' = fd' * minambient
4806                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4807                                                         //   ...
4808                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4809                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4810                                                         //   ...
4811                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4812                                                         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
4813                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4814                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4815                                                 }
4816                                         }
4817                                 }
4818
4819                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4820                                 {
4821                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4822                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4823                                         f = fa + 0.25 * fd;
4824                                         if(f > 0)
4825                                         {
4826                                                 // adjust brightness and saturation to target
4827                                                 avg[0] = avg[1] = avg[2] = fa / f;
4828                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4829                                                 avg[0] = avg[1] = avg[2] = fd / f;
4830                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4831                                         }
4832                                 }
4833                         }
4834                 }
4835                 else // highly rare
4836                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4837
4838                 // move the light direction into modelspace coordinates for lighting code
4839                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4840                 if(VectorLength2(ent->modellight_lightdir) == 0)
4841                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4842                 VectorNormalize(ent->modellight_lightdir);
4843         }
4844 }
4845
4846 #define MAX_LINEOFSIGHTTRACES 64
4847
4848 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4849 {
4850         int i;
4851         vec3_t boxmins, boxmaxs;
4852         vec3_t start;
4853         vec3_t end;
4854         dp_model_t *model = r_refdef.scene.worldmodel;
4855
4856         if (!model || !model->brush.TraceLineOfSight)
4857                 return true;
4858
4859         // expand the box a little
4860         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4861         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4862         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4863         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4864         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4865         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4866
4867         // return true if eye is inside enlarged box
4868         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4869                 return true;
4870
4871         // try center
4872         VectorCopy(eye, start);
4873         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4874         if (model->brush.TraceLineOfSight(model, start, end))
4875                 return true;
4876
4877         // try various random positions
4878         for (i = 0;i < numsamples;i++)
4879         {
4880                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4881                 if (model->brush.TraceLineOfSight(model, start, end))
4882                         return true;
4883         }
4884
4885         return false;
4886 }
4887
4888
4889 static void R_View_UpdateEntityVisible (void)
4890 {
4891         int i;
4892         int renderimask;
4893         int samples;
4894         entity_render_t *ent;
4895
4896         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4898                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4899                 :                                                          RENDER_EXTERIORMODEL;
4900         if (!r_drawviewmodel.integer)
4901                 renderimask |= RENDER_VIEWMODEL;
4902         if (!r_drawexteriormodel.integer)
4903                 renderimask |= RENDER_EXTERIORMODEL;
4904         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4905         {
4906                 // worldmodel can check visibility
4907                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4908                 for (i = 0;i < r_refdef.scene.numentities;i++)
4909                 {
4910                         ent = r_refdef.scene.entities[i];
4911                         if (!(ent->flags & renderimask))
4912                         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)))
4913                         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))
4914                                 r_refdef.viewcache.entityvisible[i] = true;
4915                 }
4916         }
4917         else
4918         {
4919                 // no worldmodel or it can't check visibility
4920                 for (i = 0;i < r_refdef.scene.numentities;i++)
4921                 {
4922                         ent = r_refdef.scene.entities[i];
4923                         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));
4924                 }
4925         }
4926         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4927                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4928         {
4929                 for (i = 0;i < r_refdef.scene.numentities;i++)
4930                 {
4931                         if (!r_refdef.viewcache.entityvisible[i])
4932                                 continue;
4933                         ent = r_refdef.scene.entities[i];
4934                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4935                         {
4936                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4937                                 if (samples < 0)
4938                                         continue; // temp entities do pvs only
4939                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4940                                         ent->last_trace_visibility = realtime;
4941                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4942                                         r_refdef.viewcache.entityvisible[i] = 0;
4943                         }
4944                 }
4945         }
4946 }
4947
4948 /// only used if skyrendermasked, and normally returns false
4949 int R_DrawBrushModelsSky (void)
4950 {
4951         int i, sky;
4952         entity_render_t *ent;
4953
4954         sky = false;
4955         for (i = 0;i < r_refdef.scene.numentities;i++)
4956         {
4957                 if (!r_refdef.viewcache.entityvisible[i])
4958                         continue;
4959                 ent = r_refdef.scene.entities[i];
4960                 if (!ent->model || !ent->model->DrawSky)
4961                         continue;
4962                 ent->model->DrawSky(ent);
4963                 sky = true;
4964         }
4965         return sky;
4966 }
4967
4968 static void R_DrawNoModel(entity_render_t *ent);
4969 static void R_DrawModels(void)
4970 {
4971         int i;
4972         entity_render_t *ent;
4973
4974         for (i = 0;i < r_refdef.scene.numentities;i++)
4975         {
4976                 if (!r_refdef.viewcache.entityvisible[i])
4977                         continue;
4978                 ent = r_refdef.scene.entities[i];
4979                 r_refdef.stats.entities++;
4980                 /*
4981                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4982                 {
4983                         vec3_t f, l, u, o;
4984                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4985                         Con_Printf("R_DrawModels\n");
4986                         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]);
4987                         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);
4988                         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);
4989                 }
4990                 */
4991                 if (ent->model && ent->model->Draw != NULL)
4992                         ent->model->Draw(ent);
4993                 else
4994                         R_DrawNoModel(ent);
4995         }
4996 }
4997
4998 static void R_DrawModelsDepth(void)
4999 {
5000         int i;
5001         entity_render_t *ent;
5002
5003         for (i = 0;i < r_refdef.scene.numentities;i++)
5004         {
5005                 if (!r_refdef.viewcache.entityvisible[i])
5006                         continue;
5007                 ent = r_refdef.scene.entities[i];
5008                 if (ent->model && ent->model->DrawDepth != NULL)
5009                         ent->model->DrawDepth(ent);
5010         }
5011 }
5012
5013 static void R_DrawModelsDebug(void)
5014 {
5015         int i;
5016         entity_render_t *ent;
5017
5018         for (i = 0;i < r_refdef.scene.numentities;i++)
5019         {
5020                 if (!r_refdef.viewcache.entityvisible[i])
5021                         continue;
5022                 ent = r_refdef.scene.entities[i];
5023                 if (ent->model && ent->model->DrawDebug != NULL)
5024                         ent->model->DrawDebug(ent);
5025         }
5026 }
5027
5028 static void R_DrawModelsAddWaterPlanes(void)
5029 {
5030         int i;
5031         entity_render_t *ent;
5032
5033         for (i = 0;i < r_refdef.scene.numentities;i++)
5034         {
5035                 if (!r_refdef.viewcache.entityvisible[i])
5036                         continue;
5037                 ent = r_refdef.scene.entities[i];
5038                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5039                         ent->model->DrawAddWaterPlanes(ent);
5040         }
5041 }
5042
5043 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5044 {
5045         if (r_hdr_irisadaptation.integer)
5046         {
5047                 vec3_t ambient;
5048                 vec3_t diffuse;
5049                 vec3_t diffusenormal;
5050                 vec_t brightness;
5051                 vec_t goal;
5052                 vec_t current;
5053                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5054                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5055                 brightness = max(0.0000001f, brightness);
5056                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5057                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5058                 current = r_hdr_irisadaptation_value.value;
5059                 if (current < goal)
5060                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5061                 else if (current > goal)
5062                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5063                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5064                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5065         }
5066         else if (r_hdr_irisadaptation_value.value != 1.0f)
5067                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5068 }
5069
5070 static void R_View_SetFrustum(const int *scissor)
5071 {
5072         int i;
5073         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5074         vec3_t forward, left, up, origin, v;
5075
5076         if(scissor)
5077         {
5078                 // flipped x coordinates (because x points left here)
5079                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5080                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5081
5082                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5083                 switch(vid.renderpath)
5084                 {
5085                         case RENDERPATH_D3D9:
5086                         case RENDERPATH_D3D10:
5087                         case RENDERPATH_D3D11:
5088                                 // non-flipped y coordinates
5089                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5090                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5091                                 break;
5092                         case RENDERPATH_SOFT:
5093                         case RENDERPATH_GL11:
5094                         case RENDERPATH_GL13:
5095                         case RENDERPATH_GL20:
5096                         case RENDERPATH_GLES1:
5097                         case RENDERPATH_GLES2:
5098                                 // non-flipped y coordinates
5099                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5100                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5101                                 break;
5102                 }
5103         }
5104
5105         // we can't trust r_refdef.view.forward and friends in reflected scenes
5106         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5107
5108 #if 0
5109         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5110         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5111         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5112         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5113         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5114         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5115         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5116         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5117         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5118         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5119         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5120         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5121 #endif
5122
5123 #if 0
5124         zNear = r_refdef.nearclip;
5125         nudge = 1.0 - 1.0 / (1<<23);
5126         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5127         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5128         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5129         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5130         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5131         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5132         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5133         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5134 #endif
5135
5136
5137
5138 #if 0
5139         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5140         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5141         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5142         r_refdef.view.frustum[0].dist = m[15] - m[12];
5143
5144         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5145         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5146         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5147         r_refdef.view.frustum[1].dist = m[15] + m[12];
5148
5149         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5150         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5151         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5152         r_refdef.view.frustum[2].dist = m[15] - m[13];
5153
5154         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5155         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5156         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5157         r_refdef.view.frustum[3].dist = m[15] + m[13];
5158
5159         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5160         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5161         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5162         r_refdef.view.frustum[4].dist = m[15] - m[14];
5163
5164         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5165         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5166         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5167         r_refdef.view.frustum[5].dist = m[15] + m[14];
5168 #endif
5169
5170         if (r_refdef.view.useperspective)
5171         {
5172                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5173                 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]);
5174                 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]);
5175                 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]);
5176                 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]);
5177
5178                 // then the normals from the corners relative to origin
5179                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5180                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5181                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5182                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5183
5184                 // in a NORMAL view, forward cross left == up
5185                 // in a REFLECTED view, forward cross left == down
5186                 // so our cross products above need to be adjusted for a left handed coordinate system
5187                 CrossProduct(forward, left, v);
5188                 if(DotProduct(v, up) < 0)
5189                 {
5190                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5191                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5192                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5193                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5194                 }
5195
5196                 // Leaving those out was a mistake, those were in the old code, and they
5197                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5198                 // I couldn't reproduce it after adding those normalizations. --blub
5199                 VectorNormalize(r_refdef.view.frustum[0].normal);
5200                 VectorNormalize(r_refdef.view.frustum[1].normal);
5201                 VectorNormalize(r_refdef.view.frustum[2].normal);
5202                 VectorNormalize(r_refdef.view.frustum[3].normal);
5203
5204                 // make the corners absolute
5205                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5206                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5207                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5208                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5209
5210                 // one more normal
5211                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5212
5213                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5214                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5215                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5216                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5217                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5218         }
5219         else
5220         {
5221                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5222                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5223                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5224                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5225                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5226                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5227                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5228                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5229                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5230                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5231         }
5232         r_refdef.view.numfrustumplanes = 5;
5233
5234         if (r_refdef.view.useclipplane)
5235         {
5236                 r_refdef.view.numfrustumplanes = 6;
5237                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5238         }
5239
5240         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5241                 PlaneClassify(r_refdef.view.frustum + i);
5242
5243         // LordHavoc: note to all quake engine coders, Quake had a special case
5244         // for 90 degrees which assumed a square view (wrong), so I removed it,
5245         // Quake2 has it disabled as well.
5246
5247         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5248         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5249         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5250         //PlaneClassify(&frustum[0]);
5251
5252         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5253         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5254         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5255         //PlaneClassify(&frustum[1]);
5256
5257         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5258         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5259         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5260         //PlaneClassify(&frustum[2]);
5261
5262         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5263         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5264         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5265         //PlaneClassify(&frustum[3]);
5266
5267         // nearclip plane
5268         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5269         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5270         //PlaneClassify(&frustum[4]);
5271 }
5272
5273 void R_View_UpdateWithScissor(const int *myscissor)
5274 {
5275         R_Main_ResizeViewCache();
5276         R_View_SetFrustum(myscissor);
5277         R_View_WorldVisibility(r_refdef.view.useclipplane);
5278         R_View_UpdateEntityVisible();
5279         R_View_UpdateEntityLighting();
5280 }
5281
5282 void R_View_Update(void)
5283 {
5284         R_Main_ResizeViewCache();
5285         R_View_SetFrustum(NULL);
5286         R_View_WorldVisibility(r_refdef.view.useclipplane);
5287         R_View_UpdateEntityVisible();
5288         R_View_UpdateEntityLighting();
5289 }
5290
5291 float viewscalefpsadjusted = 1.0f;
5292
5293 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5294 {
5295         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5296         scale = bound(0.03125f, scale, 1.0f);
5297         *outwidth = (int)ceil(width * scale);
5298         *outheight = (int)ceil(height * scale);
5299 }
5300
5301 void R_Mesh_SetMainRenderTargets(void)
5302 {
5303         if (r_bloomstate.fbo_framebuffer)
5304                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5305         else
5306                 R_Mesh_ResetRenderTargets();
5307 }
5308
5309 void R_SetupView(qboolean allowwaterclippingplane)
5310 {
5311         const float *customclipplane = NULL;
5312         float plane[4];
5313         int scaledwidth, scaledheight;
5314         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5315         {
5316                 // LordHavoc: couldn't figure out how to make this approach the
5317                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5318                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5319                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5320                         dist = r_refdef.view.clipplane.dist;
5321                 plane[0] = r_refdef.view.clipplane.normal[0];
5322                 plane[1] = r_refdef.view.clipplane.normal[1];
5323                 plane[2] = r_refdef.view.clipplane.normal[2];
5324                 plane[3] = -dist;
5325                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5326         }
5327
5328         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5329         if (!r_refdef.view.useperspective)
5330                 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);
5331         else if (vid.stencil && r_useinfinitefarclip.integer)
5332                 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);
5333         else
5334                 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);
5335         R_Mesh_SetMainRenderTargets();
5336         R_SetViewport(&r_refdef.view.viewport);
5337         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5338         {
5339                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5340                 float screenplane[4];
5341                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5342                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5343                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5344                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5345                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5346         }
5347 }
5348
5349 void R_EntityMatrix(const matrix4x4_t *matrix)
5350 {
5351         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5352         {
5353                 gl_modelmatrixchanged = false;
5354                 gl_modelmatrix = *matrix;
5355                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5356                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5357                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5358                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5359                 CHECKGLERROR
5360                 switch(vid.renderpath)
5361                 {
5362                 case RENDERPATH_D3D9:
5363 #ifdef SUPPORTD3D
5364                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5365                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5366 #endif
5367                         break;
5368                 case RENDERPATH_D3D10:
5369                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5370                         break;
5371                 case RENDERPATH_D3D11:
5372                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5373                         break;
5374                 case RENDERPATH_GL11:
5375                 case RENDERPATH_GL13:
5376                 case RENDERPATH_GLES1:
5377                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5378                         break;
5379                 case RENDERPATH_SOFT:
5380                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5381                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5382                         break;
5383                 case RENDERPATH_GL20:
5384                 case RENDERPATH_GLES2:
5385                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5386                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5387                         break;
5388                 }
5389         }
5390 }
5391
5392 void R_ResetViewRendering2D(void)
5393 {
5394         r_viewport_t viewport;
5395         DrawQ_Finish();
5396
5397         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5398         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);
5399         R_Mesh_ResetRenderTargets();
5400         R_SetViewport(&viewport);
5401         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5402         GL_Color(1, 1, 1, 1);
5403         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5404         GL_BlendFunc(GL_ONE, GL_ZERO);
5405         GL_ScissorTest(false);
5406         GL_DepthMask(false);
5407         GL_DepthRange(0, 1);
5408         GL_DepthTest(false);
5409         GL_DepthFunc(GL_LEQUAL);
5410         R_EntityMatrix(&identitymatrix);
5411         R_Mesh_ResetTextureState();
5412         GL_PolygonOffset(0, 0);
5413         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5414         switch(vid.renderpath)
5415         {
5416         case RENDERPATH_GL11:
5417         case RENDERPATH_GL13:
5418         case RENDERPATH_GL20:
5419         case RENDERPATH_GLES1:
5420         case RENDERPATH_GLES2:
5421                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5422                 break;
5423         case RENDERPATH_D3D9:
5424         case RENDERPATH_D3D10:
5425         case RENDERPATH_D3D11:
5426         case RENDERPATH_SOFT:
5427                 break;
5428         }
5429         GL_CullFace(GL_NONE);
5430 }
5431
5432 void R_ResetViewRendering3D(void)
5433 {
5434         DrawQ_Finish();
5435
5436         R_SetupView(true);
5437         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5438         GL_Color(1, 1, 1, 1);
5439         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5440         GL_BlendFunc(GL_ONE, GL_ZERO);
5441         GL_ScissorTest(true);
5442         GL_DepthMask(true);
5443         GL_DepthRange(0, 1);
5444         GL_DepthTest(true);
5445         GL_DepthFunc(GL_LEQUAL);
5446         R_EntityMatrix(&identitymatrix);
5447         R_Mesh_ResetTextureState();
5448         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5449         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5450         switch(vid.renderpath)
5451         {
5452         case RENDERPATH_GL11:
5453         case RENDERPATH_GL13:
5454         case RENDERPATH_GL20:
5455         case RENDERPATH_GLES1:
5456         case RENDERPATH_GLES2:
5457                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5458                 break;
5459         case RENDERPATH_D3D9:
5460         case RENDERPATH_D3D10:
5461         case RENDERPATH_D3D11:
5462         case RENDERPATH_SOFT:
5463                 break;
5464         }
5465         GL_CullFace(r_refdef.view.cullface_back);
5466 }
5467
5468 /*
5469 ================
5470 R_RenderView_UpdateViewVectors
5471 ================
5472 */
5473 static void R_RenderView_UpdateViewVectors(void)
5474 {
5475         // break apart the view matrix into vectors for various purposes
5476         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5477         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5478         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5479         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5480         // make an inverted copy of the view matrix for tracking sprites
5481         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5482 }
5483
5484 void R_RenderScene(void);
5485 void R_RenderWaterPlanes(void);
5486
5487 static void R_Water_StartFrame(void)
5488 {
5489         int i;
5490         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5491         r_waterstate_waterplane_t *p;
5492
5493         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5494                 return;
5495
5496         switch(vid.renderpath)
5497         {
5498         case RENDERPATH_GL20:
5499         case RENDERPATH_D3D9:
5500         case RENDERPATH_D3D10:
5501         case RENDERPATH_D3D11:
5502         case RENDERPATH_SOFT:
5503         case RENDERPATH_GLES2:
5504                 break;
5505         case RENDERPATH_GL11:
5506         case RENDERPATH_GL13:
5507         case RENDERPATH_GLES1:
5508                 return;
5509         }
5510
5511         // set waterwidth and waterheight to the water resolution that will be
5512         // used (often less than the screen resolution for faster rendering)
5513         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5514
5515         // calculate desired texture sizes
5516         // can't use water if the card does not support the texture size
5517         if (!r_water.integer || r_showsurfaces.integer)
5518                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5519         else if (vid.support.arb_texture_non_power_of_two)
5520         {
5521                 texturewidth = waterwidth;
5522                 textureheight = waterheight;
5523                 camerawidth = waterwidth;
5524                 cameraheight = waterheight;
5525         }
5526         else
5527         {
5528                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5529                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5530                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5531                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5532         }
5533
5534         // allocate textures as needed
5535         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5536         {
5537                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5538                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5539                 {
5540                         if (p->texture_refraction)
5541                                 R_FreeTexture(p->texture_refraction);
5542                         p->texture_refraction = NULL;
5543                         if (p->texture_reflection)
5544                                 R_FreeTexture(p->texture_reflection);
5545                         p->texture_reflection = NULL;
5546                         if (p->texture_camera)
5547                                 R_FreeTexture(p->texture_camera);
5548                         p->texture_camera = NULL;
5549                 }
5550                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5551                 r_waterstate.texturewidth = texturewidth;
5552                 r_waterstate.textureheight = textureheight;
5553                 r_waterstate.camerawidth = camerawidth;
5554                 r_waterstate.cameraheight = cameraheight;
5555         }
5556
5557         if (r_waterstate.texturewidth)
5558         {
5559                 int scaledwidth, scaledheight;
5560
5561                 r_waterstate.enabled = true;
5562
5563                 // when doing a reduced render (HDR) we want to use a smaller area
5564                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5565                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5566                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5567
5568                 // set up variables that will be used in shader setup
5569                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5570                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5571                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5572                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5573         }
5574
5575         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5576         r_waterstate.numwaterplanes = 0;
5577 }
5578
5579 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5580 {
5581         int triangleindex, planeindex;
5582         const int *e;
5583         vec3_t vert[3];
5584         vec3_t normal;
5585         vec3_t center;
5586         mplane_t plane;
5587         r_waterstate_waterplane_t *p;
5588         texture_t *t = R_GetCurrentTexture(surface->texture);
5589
5590         // just use the first triangle with a valid normal for any decisions
5591         VectorClear(normal);
5592         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5593         {
5594                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5595                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5596                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5597                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5598                 if (VectorLength2(normal) >= 0.001)
5599                         break;
5600         }
5601
5602         VectorCopy(normal, plane.normal);
5603         VectorNormalize(plane.normal);
5604         plane.dist = DotProduct(vert[0], plane.normal);
5605         PlaneClassify(&plane);
5606         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5607         {
5608                 // skip backfaces (except if nocullface is set)
5609                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5610                         return;
5611                 VectorNegate(plane.normal, plane.normal);
5612                 plane.dist *= -1;
5613                 PlaneClassify(&plane);
5614         }
5615
5616
5617         // find a matching plane if there is one
5618         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5619                 if(p->camera_entity == t->camera_entity)
5620                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5621                                 break;
5622         if (planeindex >= r_waterstate.maxwaterplanes)
5623                 return; // nothing we can do, out of planes
5624
5625         // if this triangle does not fit any known plane rendered this frame, add one
5626         if (planeindex >= r_waterstate.numwaterplanes)
5627         {
5628                 // store the new plane
5629                 r_waterstate.numwaterplanes++;
5630                 p->plane = plane;
5631                 // clear materialflags and pvs
5632                 p->materialflags = 0;
5633                 p->pvsvalid = false;
5634                 p->camera_entity = t->camera_entity;
5635                 VectorCopy(surface->mins, p->mins);
5636                 VectorCopy(surface->maxs, p->maxs);
5637         }
5638         else
5639         {
5640                 // merge mins/maxs
5641                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5642                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5643                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5644                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5645                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5646                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5647         }
5648         // merge this surface's materialflags into the waterplane
5649         p->materialflags |= t->currentmaterialflags;
5650         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5651         {
5652                 // merge this surface's PVS into the waterplane
5653                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5654                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5655                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5656                 {
5657                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5658                         p->pvsvalid = true;
5659                 }
5660         }
5661 }
5662
5663 extern cvar_t r_drawparticles;
5664 extern cvar_t r_drawdecals;
5665
5666 static void R_Water_ProcessPlanes(void)
5667 {
5668         int myscissor[4];
5669         r_refdef_view_t originalview;
5670         r_refdef_view_t myview;
5671         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;
5672         r_waterstate_waterplane_t *p;
5673         vec3_t visorigin;
5674
5675         originalview = r_refdef.view;
5676
5677         // lowquality hack, temporarily shut down some cvars and restore afterwards
5678         qualityreduction = r_water_lowquality.integer;
5679         if (qualityreduction > 0)
5680         {
5681                 if (qualityreduction >= 1)
5682                 {
5683                         old_r_shadows = r_shadows.integer;
5684                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5685                         old_r_dlight = r_shadow_realtime_dlight.integer;
5686                         Cvar_SetValueQuick(&r_shadows, 0);
5687                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5688                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5689                 }
5690                 if (qualityreduction >= 2)
5691                 {
5692                         old_r_dynamic = r_dynamic.integer;
5693                         old_r_particles = r_drawparticles.integer;
5694                         old_r_decals = r_drawdecals.integer;
5695                         Cvar_SetValueQuick(&r_dynamic, 0);
5696                         Cvar_SetValueQuick(&r_drawparticles, 0);
5697                         Cvar_SetValueQuick(&r_drawdecals, 0);
5698                 }
5699         }
5700
5701         // make sure enough textures are allocated
5702         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5703         {
5704                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5705                 {
5706                         if (!p->texture_refraction)
5707                                 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);
5708                         if (!p->texture_refraction)
5709                                 goto error;
5710                 }
5711                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5712                 {
5713                         if (!p->texture_camera)
5714                                 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);
5715                         if (!p->texture_camera)
5716                                 goto error;
5717                 }
5718
5719                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5720                 {
5721                         if (!p->texture_reflection)
5722                                 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);
5723                         if (!p->texture_reflection)
5724                                 goto error;
5725                 }
5726         }
5727
5728         // render views
5729         r_refdef.view = originalview;
5730         r_refdef.view.showdebug = false;
5731         r_refdef.view.width = r_waterstate.waterwidth;
5732         r_refdef.view.height = r_waterstate.waterheight;
5733         r_refdef.view.useclipplane = true;
5734         myview = r_refdef.view;
5735         r_waterstate.renderingscene = true;
5736         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5737         {
5738                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5739                 {
5740                         r_refdef.view = myview;
5741                         if(r_water_scissormode.integer)
5742                         {
5743                                 R_SetupView(true);
5744                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5745                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5746                         }
5747
5748                         // render reflected scene and copy into texture
5749                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5750                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5751                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5752                         r_refdef.view.clipplane = p->plane;
5753                         // reverse the cullface settings for this render
5754                         r_refdef.view.cullface_front = GL_FRONT;
5755                         r_refdef.view.cullface_back = GL_BACK;
5756                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5757                         {
5758                                 r_refdef.view.usecustompvs = true;
5759                                 if (p->pvsvalid)
5760                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5761                                 else
5762                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5763                         }
5764
5765                         R_ResetViewRendering3D();
5766                         R_ClearScreen(r_refdef.fogenabled);
5767                         if(r_water_scissormode.integer & 2)
5768                                 R_View_UpdateWithScissor(myscissor);
5769                         else
5770                                 R_View_Update();
5771                         if(r_water_scissormode.integer & 1)
5772                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5773                         R_RenderScene();
5774
5775                         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);
5776                 }
5777
5778                 // render the normal view scene and copy into texture
5779                 // (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)
5780                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5781                 {
5782                         r_refdef.view = myview;
5783                         if(r_water_scissormode.integer)
5784                         {
5785                                 R_SetupView(true);
5786                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5787                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5788                         }
5789
5790                         r_waterstate.renderingrefraction = true;
5791
5792                         r_refdef.view.clipplane = p->plane;
5793                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5794                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5795
5796                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5797                         {
5798                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5799                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5800                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5801                                 R_RenderView_UpdateViewVectors();
5802                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5803                                 {
5804                                         r_refdef.view.usecustompvs = true;
5805                                         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);
5806                                 }
5807                         }
5808
5809                         PlaneClassify(&r_refdef.view.clipplane);
5810
5811                         R_ResetViewRendering3D();
5812                         R_ClearScreen(r_refdef.fogenabled);
5813                         if(r_water_scissormode.integer & 2)
5814                                 R_View_UpdateWithScissor(myscissor);
5815                         else
5816                                 R_View_Update();
5817                         if(r_water_scissormode.integer & 1)
5818                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5819                         R_RenderScene();
5820
5821                         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);
5822                         r_waterstate.renderingrefraction = false;
5823                 }
5824                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5825                 {
5826                         r_refdef.view = myview;
5827
5828                         r_refdef.view.clipplane = p->plane;
5829                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5830                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5831
5832                         r_refdef.view.width = r_waterstate.camerawidth;
5833                         r_refdef.view.height = r_waterstate.cameraheight;
5834                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5835                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5836
5837                         if(p->camera_entity)
5838                         {
5839                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5840                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5841                         }
5842
5843                         // note: all of the view is used for displaying... so
5844                         // there is no use in scissoring
5845
5846                         // reverse the cullface settings for this render
5847                         r_refdef.view.cullface_front = GL_FRONT;
5848                         r_refdef.view.cullface_back = GL_BACK;
5849                         // also reverse the view matrix
5850                         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
5851                         R_RenderView_UpdateViewVectors();
5852                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5853                         {
5854                                 r_refdef.view.usecustompvs = true;
5855                                 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);
5856                         }
5857                         
5858                         // camera needs no clipplane
5859                         r_refdef.view.useclipplane = false;
5860
5861                         PlaneClassify(&r_refdef.view.clipplane);
5862
5863                         R_ResetViewRendering3D();
5864                         R_ClearScreen(r_refdef.fogenabled);
5865                         R_View_Update();
5866                         R_RenderScene();
5867
5868                         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);
5869                         r_waterstate.renderingrefraction = false;
5870                 }
5871
5872         }
5873         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5874         r_waterstate.renderingscene = false;
5875         r_refdef.view = originalview;
5876         R_ResetViewRendering3D();
5877         R_ClearScreen(r_refdef.fogenabled);
5878         R_View_Update();
5879         goto finish;
5880 error:
5881         r_refdef.view = originalview;
5882         r_waterstate.renderingscene = false;
5883         Cvar_SetValueQuick(&r_water, 0);
5884         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5885 finish:
5886         // lowquality hack, restore cvars
5887         if (qualityreduction > 0)
5888         {
5889                 if (qualityreduction >= 1)
5890                 {
5891                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5892                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5893                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5894                 }
5895                 if (qualityreduction >= 2)
5896                 {
5897                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5898                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5899                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5900                 }
5901         }
5902 }
5903
5904 void R_Bloom_StartFrame(void)
5905 {
5906         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5907         int viewwidth, viewheight;
5908         textype_t textype;
5909
5910         if (r_viewscale_fpsscaling.integer)
5911         {
5912                 double actualframetime;
5913                 double targetframetime;
5914                 double adjust;
5915                 actualframetime = r_refdef.lastdrawscreentime;
5916                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5917                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5918                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5919                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5920                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5921                 viewscalefpsadjusted += adjust;
5922                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5923         }
5924         else
5925                 viewscalefpsadjusted = 1.0f;
5926
5927         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5928
5929         switch(vid.renderpath)
5930         {
5931         case RENDERPATH_GL20:
5932         case RENDERPATH_D3D9:
5933         case RENDERPATH_D3D10:
5934         case RENDERPATH_D3D11:
5935         case RENDERPATH_SOFT:
5936         case RENDERPATH_GLES2:
5937                 break;
5938         case RENDERPATH_GL11:
5939         case RENDERPATH_GL13:
5940         case RENDERPATH_GLES1:
5941                 return;
5942         }
5943
5944         // set bloomwidth and bloomheight to the bloom resolution that will be
5945         // used (often less than the screen resolution for faster rendering)
5946         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5947         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5948         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5949         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5950         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5951
5952         // calculate desired texture sizes
5953         if (vid.support.arb_texture_non_power_of_two)
5954         {
5955                 screentexturewidth = vid.width;
5956                 screentextureheight = vid.height;
5957                 bloomtexturewidth = r_bloomstate.bloomwidth;
5958                 bloomtextureheight = r_bloomstate.bloomheight;
5959         }
5960         else
5961         {
5962                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5963                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5964                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5965                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5966         }
5967
5968         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))
5969         {
5970                 Cvar_SetValueQuick(&r_hdr, 0);
5971                 Cvar_SetValueQuick(&r_bloom, 0);
5972                 Cvar_SetValueQuick(&r_motionblur, 0);
5973                 Cvar_SetValueQuick(&r_damageblur, 0);
5974         }
5975
5976         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)
5977                 screentexturewidth = screentextureheight = 0;
5978         if (!r_hdr.integer && !r_bloom.integer)
5979                 bloomtexturewidth = bloomtextureheight = 0;
5980
5981         textype = TEXTYPE_COLORBUFFER;
5982         switch (vid.renderpath)
5983         {
5984         case RENDERPATH_GL20:
5985         case RENDERPATH_GLES2:
5986                 if (vid.support.ext_framebuffer_object)
5987                 {
5988                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5989                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5990                 }
5991                 break;
5992         case RENDERPATH_GL11:
5993         case RENDERPATH_GL13:
5994         case RENDERPATH_GLES1:
5995         case RENDERPATH_D3D9:
5996         case RENDERPATH_D3D10:
5997         case RENDERPATH_D3D11:
5998         case RENDERPATH_SOFT:
5999                 break;
6000         }
6001
6002         // allocate textures as needed
6003         if (r_bloomstate.screentexturewidth != screentexturewidth
6004          || r_bloomstate.screentextureheight != screentextureheight
6005          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6006          || r_bloomstate.bloomtextureheight != bloomtextureheight
6007          || r_bloomstate.texturetype != textype
6008          || r_bloomstate.viewfbo != r_viewfbo.integer)
6009         {
6010                 if (r_bloomstate.texture_bloom)
6011                         R_FreeTexture(r_bloomstate.texture_bloom);
6012                 r_bloomstate.texture_bloom = NULL;
6013                 if (r_bloomstate.texture_screen)
6014                         R_FreeTexture(r_bloomstate.texture_screen);
6015                 r_bloomstate.texture_screen = NULL;
6016                 if (r_bloomstate.fbo_framebuffer)
6017                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6018                 r_bloomstate.fbo_framebuffer = 0;
6019                 if (r_bloomstate.texture_framebuffercolor)
6020                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6021                 r_bloomstate.texture_framebuffercolor = NULL;
6022                 if (r_bloomstate.texture_framebufferdepth)
6023                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6024                 r_bloomstate.texture_framebufferdepth = NULL;
6025                 r_bloomstate.screentexturewidth = screentexturewidth;
6026                 r_bloomstate.screentextureheight = screentextureheight;
6027                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6028                         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);
6029                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6030                 {
6031                         // FIXME: choose depth bits based on a cvar
6032                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6033                         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);
6034                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6035                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6036 #ifndef USE_GLES2
6037                         // render depth into one texture and normalmap into the other
6038                         if (qglDrawBuffer)
6039                         {
6040                                 int status;
6041                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6042                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6043                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6044                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6045                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6046                         }
6047 #endif
6048                 }
6049                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6050                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6051                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6052                         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);
6053                 r_bloomstate.viewfbo = r_viewfbo.integer;
6054                 r_bloomstate.texturetype = textype;
6055         }
6056
6057         // when doing a reduced render (HDR) we want to use a smaller area
6058         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6059         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6060         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6061         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6062         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6063
6064         // set up a texcoord array for the full resolution screen image
6065         // (we have to keep this around to copy back during final render)
6066         r_bloomstate.screentexcoord2f[0] = 0;
6067         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6068         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6069         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6070         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6071         r_bloomstate.screentexcoord2f[5] = 0;
6072         r_bloomstate.screentexcoord2f[6] = 0;
6073         r_bloomstate.screentexcoord2f[7] = 0;
6074
6075         // set up a texcoord array for the reduced resolution bloom image
6076         // (which will be additive blended over the screen image)
6077         r_bloomstate.bloomtexcoord2f[0] = 0;
6078         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6079         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6080         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6081         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6082         r_bloomstate.bloomtexcoord2f[5] = 0;
6083         r_bloomstate.bloomtexcoord2f[6] = 0;
6084         r_bloomstate.bloomtexcoord2f[7] = 0;
6085
6086         switch(vid.renderpath)
6087         {
6088         case RENDERPATH_GL11:
6089         case RENDERPATH_GL13:
6090         case RENDERPATH_GL20:
6091         case RENDERPATH_SOFT:
6092         case RENDERPATH_GLES1:
6093         case RENDERPATH_GLES2:
6094                 break;
6095         case RENDERPATH_D3D9:
6096         case RENDERPATH_D3D10:
6097         case RENDERPATH_D3D11:
6098                 {
6099                         int i;
6100                         for (i = 0;i < 4;i++)
6101                         {
6102                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6103                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6104                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6105                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6106                         }
6107                 }
6108                 break;
6109         }
6110
6111         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6112         {
6113                 r_bloomstate.enabled = true;
6114                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6115         }
6116
6117         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);
6118
6119         if (r_bloomstate.fbo_framebuffer)
6120                 r_refdef.view.clear = true;
6121 }
6122
6123 void R_Bloom_CopyBloomTexture(float colorscale)
6124 {
6125         r_refdef.stats.bloom++;
6126
6127         // scale down screen texture to the bloom texture size
6128         CHECKGLERROR
6129         R_Mesh_SetMainRenderTargets();
6130         R_SetViewport(&r_bloomstate.viewport);
6131         GL_BlendFunc(GL_ONE, GL_ZERO);
6132         GL_Color(colorscale, colorscale, colorscale, 1);
6133         // 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...
6134         switch(vid.renderpath)
6135         {
6136         case RENDERPATH_GL11:
6137         case RENDERPATH_GL13:
6138         case RENDERPATH_GL20:
6139         case RENDERPATH_GLES1:
6140         case RENDERPATH_GLES2:
6141         case RENDERPATH_SOFT:
6142                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6143                 break;
6144         case RENDERPATH_D3D9:
6145         case RENDERPATH_D3D10:
6146         case RENDERPATH_D3D11:
6147                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6148                 break;
6149         }
6150         // TODO: do boxfilter scale-down in shader?
6151         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6152         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6153         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6154
6155         // we now have a bloom image in the framebuffer
6156         // copy it into the bloom image texture for later processing
6157         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);
6158         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6159 }
6160
6161 void R_Bloom_CopyHDRTexture(void)
6162 {
6163         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);
6164         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6165 }
6166
6167 void R_Bloom_MakeTexture(void)
6168 {
6169         int x, range, dir;
6170         float xoffset, yoffset, r, brighten;
6171
6172         r_refdef.stats.bloom++;
6173
6174         R_ResetViewRendering2D();
6175
6176         // we have a bloom image in the framebuffer
6177         CHECKGLERROR
6178         R_SetViewport(&r_bloomstate.viewport);
6179
6180         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6181         {
6182                 x *= 2;
6183                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6184                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6185                 GL_Color(r,r,r,1);
6186                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6187                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6188                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6189                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6190
6191                 // copy the vertically blurred bloom view to a texture
6192                 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);
6193                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6194         }
6195
6196         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6197         brighten = r_bloom_brighten.value;
6198         if (r_bloomstate.hdr)
6199                 brighten *= r_hdr_range.value;
6200         brighten = sqrt(brighten);
6201         if(range >= 1)
6202                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6203         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6204
6205         for (dir = 0;dir < 2;dir++)
6206         {
6207                 // blend on at multiple vertical offsets to achieve a vertical blur
6208                 // TODO: do offset blends using GLSL
6209                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6210                 GL_BlendFunc(GL_ONE, GL_ZERO);
6211                 for (x = -range;x <= range;x++)
6212                 {
6213                         if (!dir){xoffset = 0;yoffset = x;}
6214                         else {xoffset = x;yoffset = 0;}
6215                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6216                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6217                         // compute a texcoord array with the specified x and y offset
6218                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6219                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6220                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6221                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6222                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6223                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6224                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6225                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6226                         // this r value looks like a 'dot' particle, fading sharply to
6227                         // black at the edges
6228                         // (probably not realistic but looks good enough)
6229                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6230                         //r = brighten/(range*2+1);
6231                         r = brighten / (range * 2 + 1);
6232                         if(range >= 1)
6233                                 r *= (1 - x*x/(float)(range*range));
6234                         GL_Color(r, r, r, 1);
6235                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6236                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6237                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6238                         GL_BlendFunc(GL_ONE, GL_ONE);
6239                 }
6240
6241                 // copy the vertically blurred bloom view to a texture
6242                 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);
6243                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6244         }
6245 }
6246
6247 void R_HDR_RenderBloomTexture(void)
6248 {
6249         int oldwidth, oldheight;
6250         float oldcolorscale;
6251         qboolean oldwaterstate;
6252
6253         oldwaterstate = r_waterstate.enabled;
6254         oldcolorscale = r_refdef.view.colorscale;
6255         oldwidth = r_refdef.view.width;
6256         oldheight = r_refdef.view.height;
6257         r_refdef.view.width = r_bloomstate.bloomwidth;
6258         r_refdef.view.height = r_bloomstate.bloomheight;
6259
6260         if(r_hdr.integer < 2)
6261                 r_waterstate.enabled = false;
6262
6263         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6264         // TODO: add exposure compensation features
6265         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6266
6267         r_refdef.view.showdebug = false;
6268         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6269
6270         R_ResetViewRendering3D();
6271
6272         R_ClearScreen(r_refdef.fogenabled);
6273         if (r_timereport_active)
6274                 R_TimeReport("HDRclear");
6275
6276         R_View_Update();
6277         if (r_timereport_active)
6278                 R_TimeReport("visibility");
6279
6280         // only do secondary renders with HDR if r_hdr is 2 or higher
6281         r_waterstate.numwaterplanes = 0;
6282         if (r_waterstate.enabled)
6283                 R_RenderWaterPlanes();
6284
6285         r_refdef.view.showdebug = true;
6286         R_RenderScene();
6287         r_waterstate.numwaterplanes = 0;
6288
6289         R_ResetViewRendering2D();
6290
6291         R_Bloom_CopyHDRTexture();
6292         R_Bloom_MakeTexture();
6293
6294         // restore the view settings
6295         r_waterstate.enabled = oldwaterstate;
6296         r_refdef.view.width = oldwidth;
6297         r_refdef.view.height = oldheight;
6298         r_refdef.view.colorscale = oldcolorscale;
6299
6300         R_ResetViewRendering3D();
6301
6302         R_ClearScreen(r_refdef.fogenabled);
6303         if (r_timereport_active)
6304                 R_TimeReport("viewclear");
6305 }
6306
6307 static void R_BlendView(void)
6308 {
6309         unsigned int permutation;
6310         float uservecs[4][4];
6311
6312         switch (vid.renderpath)
6313         {
6314         case RENDERPATH_GL20:
6315         case RENDERPATH_D3D9:
6316         case RENDERPATH_D3D10:
6317         case RENDERPATH_D3D11:
6318         case RENDERPATH_SOFT:
6319         case RENDERPATH_GLES2:
6320                 permutation =
6321                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6322                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6323                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6324                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6325                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6326
6327                 if (r_bloomstate.texture_screen)
6328                 {
6329                         // make sure the buffer is available
6330                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6331
6332                         R_ResetViewRendering2D();
6333                         R_Mesh_SetMainRenderTargets();
6334
6335                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6336                         {
6337                                 // declare variables
6338                                 float blur_factor, blur_mouseaccel, blur_velocity;
6339                                 static float blur_average; 
6340                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6341
6342                                 // set a goal for the factoring
6343                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6344                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6345                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6346                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6347                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6348                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6349
6350                                 // from the goal, pick an averaged value between goal and last value
6351                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6352                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6353                                 
6354                                 // enforce minimum amount of blur 
6355                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6356                                 
6357                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6358
6359                                 // calculate values into a standard alpha
6360                                 cl.motionbluralpha = 1 - exp(-
6361                                                 (
6362                                                  (r_motionblur.value * blur_factor / 80)
6363                                                  +
6364                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6365                                                 )
6366                                                 /
6367                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6368                                           );
6369                                 
6370                                 // randomization for the blur value to combat persistent ghosting
6371                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6372                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6373                                 
6374                                 // apply the blur
6375                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6376                                 {
6377                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6378                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6379                                         switch(vid.renderpath)
6380                                         {
6381                                         case RENDERPATH_GL11:
6382                                         case RENDERPATH_GL13:
6383                                         case RENDERPATH_GL20:
6384                                         case RENDERPATH_GLES1:
6385                                         case RENDERPATH_GLES2:
6386                                         case RENDERPATH_SOFT:
6387                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6388                                                 break;
6389                                         case RENDERPATH_D3D9:
6390                                         case RENDERPATH_D3D10:
6391                                         case RENDERPATH_D3D11:
6392                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6393                                                 break;
6394                                         }
6395                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6396                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6397                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6398                                 }
6399                                 
6400                                 // updates old view angles for next pass 
6401                                 VectorCopy(cl.viewangles, blur_oldangles);
6402                         }
6403
6404                         // copy view into the screen texture
6405                         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);
6406                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6407                 }
6408                 else if (!r_bloomstate.texture_bloom)
6409                 {
6410                         // we may still have to do view tint...
6411                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6412                         {
6413                                 // apply a color tint to the whole view
6414                                 R_ResetViewRendering2D();
6415                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6416                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6417                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6418                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6419                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6420                         }
6421                         break; // no screen processing, no bloom, skip it
6422                 }
6423
6424                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6425                 {
6426                         // render simple bloom effect
6427                         // copy the screen and shrink it and darken it for the bloom process
6428                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6429                         // make the bloom texture
6430                         R_Bloom_MakeTexture();
6431                 }
6432
6433 #if _MSC_VER >= 1400
6434 #define sscanf sscanf_s
6435 #endif
6436                 memset(uservecs, 0, sizeof(uservecs));
6437                 if (r_glsl_postprocess_uservec1_enable.integer)
6438                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6439                 if (r_glsl_postprocess_uservec2_enable.integer)
6440                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6441                 if (r_glsl_postprocess_uservec3_enable.integer)
6442                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6443                 if (r_glsl_postprocess_uservec4_enable.integer)
6444                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6445
6446                 R_ResetViewRendering2D();
6447                 GL_Color(1, 1, 1, 1);
6448                 GL_BlendFunc(GL_ONE, GL_ZERO);
6449
6450                 switch(vid.renderpath)
6451                 {
6452                 case RENDERPATH_GL20:
6453                 case RENDERPATH_GLES2:
6454                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6455                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6456                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6457                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6458                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6459                         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]);
6460                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6461                         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]);
6462                         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]);
6463                         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]);
6464                         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]);
6465                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6466                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6467                         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);
6468                         break;
6469                 case RENDERPATH_D3D9:
6470 #ifdef SUPPORTD3D
6471                         // 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...
6472                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6473                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6474                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6475                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6476                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6477                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6478                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6479                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6480                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6481                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6482                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6483                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6484                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6485                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6486 #endif
6487                         break;
6488                 case RENDERPATH_D3D10:
6489                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6490                         break;
6491                 case RENDERPATH_D3D11:
6492                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6493                         break;
6494                 case RENDERPATH_SOFT:
6495                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6496                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6497                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6498                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6499                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6500                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6501                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6502                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6503                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6504                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6505                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6506                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6507                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6508                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6509                         break;
6510                 default:
6511                         break;
6512                 }
6513                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6514                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6515                 break;
6516         case RENDERPATH_GL11:
6517         case RENDERPATH_GL13:
6518         case RENDERPATH_GLES1:
6519                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6520                 {
6521                         // apply a color tint to the whole view
6522                         R_ResetViewRendering2D();
6523                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6524                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6525                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6526                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6527                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6528                 }
6529                 break;
6530         }
6531 }
6532
6533 matrix4x4_t r_waterscrollmatrix;
6534
6535 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6536 {
6537         if (r_refdef.fog_density)
6538         {
6539                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6540                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6541                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6542
6543                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6544                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6545                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6546                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6547
6548                 {
6549                         vec3_t fogvec;
6550                         VectorCopy(r_refdef.fogcolor, fogvec);
6551                         //   color.rgb *= ContrastBoost * SceneBrightness;
6552                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6553                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6554                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6555                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6556                 }
6557         }
6558 }
6559
6560 void R_UpdateVariables(void)
6561 {
6562         R_Textures_Frame();
6563
6564         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6565
6566         r_refdef.farclip = r_farclip_base.value;
6567         if (r_refdef.scene.worldmodel)
6568                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6569         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6570
6571         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6572                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6573         r_refdef.polygonfactor = 0;
6574         r_refdef.polygonoffset = 0;
6575         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6576         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6577
6578         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6579         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6580         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6581         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6582         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6583         if (FAKELIGHT_ENABLED)
6584         {
6585                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6586         }
6587         if (r_showsurfaces.integer)
6588         {
6589                 r_refdef.scene.rtworld = false;
6590                 r_refdef.scene.rtworldshadows = false;
6591                 r_refdef.scene.rtdlight = false;
6592                 r_refdef.scene.rtdlightshadows = false;
6593                 r_refdef.lightmapintensity = 0;
6594         }
6595
6596         if (gamemode == GAME_NEHAHRA)
6597         {
6598                 if (gl_fogenable.integer)
6599                 {
6600                         r_refdef.oldgl_fogenable = true;
6601                         r_refdef.fog_density = gl_fogdensity.value;
6602                         r_refdef.fog_red = gl_fogred.value;
6603                         r_refdef.fog_green = gl_foggreen.value;
6604                         r_refdef.fog_blue = gl_fogblue.value;
6605                         r_refdef.fog_alpha = 1;
6606                         r_refdef.fog_start = 0;
6607                         r_refdef.fog_end = gl_skyclip.value;
6608                         r_refdef.fog_height = 1<<30;
6609                         r_refdef.fog_fadedepth = 128;
6610                 }
6611                 else if (r_refdef.oldgl_fogenable)
6612                 {
6613                         r_refdef.oldgl_fogenable = false;
6614                         r_refdef.fog_density = 0;
6615                         r_refdef.fog_red = 0;
6616                         r_refdef.fog_green = 0;
6617                         r_refdef.fog_blue = 0;
6618                         r_refdef.fog_alpha = 0;
6619                         r_refdef.fog_start = 0;
6620                         r_refdef.fog_end = 0;
6621                         r_refdef.fog_height = 1<<30;
6622                         r_refdef.fog_fadedepth = 128;
6623                 }
6624         }
6625
6626         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6627         r_refdef.fog_start = max(0, r_refdef.fog_start);
6628         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6629
6630         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6631
6632         if (r_refdef.fog_density && r_drawfog.integer)
6633         {
6634                 r_refdef.fogenabled = true;
6635                 // this is the point where the fog reaches 0.9986 alpha, which we
6636                 // consider a good enough cutoff point for the texture
6637                 // (0.9986 * 256 == 255.6)
6638                 if (r_fog_exp2.integer)
6639                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6640                 else
6641                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6642                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6643                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6644                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6645                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6646                         R_BuildFogHeightTexture();
6647                 // fog color was already set
6648                 // update the fog texture
6649                 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)
6650                         R_BuildFogTexture();
6651                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6652                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6653         }
6654         else
6655                 r_refdef.fogenabled = false;
6656
6657         switch(vid.renderpath)
6658         {
6659         case RENDERPATH_GL20:
6660         case RENDERPATH_D3D9:
6661         case RENDERPATH_D3D10:
6662         case RENDERPATH_D3D11:
6663         case RENDERPATH_SOFT:
6664         case RENDERPATH_GLES2:
6665                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6666                 {
6667                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6668                         {
6669                                 // build GLSL gamma texture
6670 #define RAMPWIDTH 256
6671                                 unsigned short ramp[RAMPWIDTH * 3];
6672                                 unsigned char rampbgr[RAMPWIDTH][4];
6673                                 int i;
6674
6675                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6676
6677                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6678                                 for(i = 0; i < RAMPWIDTH; ++i)
6679                                 {
6680                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6681                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6682                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6683                                         rampbgr[i][3] = 0;
6684                                 }
6685                                 if (r_texture_gammaramps)
6686                                 {
6687                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6688                                 }
6689                                 else
6690                                 {
6691                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6692                                 }
6693                         }
6694                 }
6695                 else
6696                 {
6697                         // remove GLSL gamma texture
6698                 }
6699                 break;
6700         case RENDERPATH_GL11:
6701         case RENDERPATH_GL13:
6702         case RENDERPATH_GLES1:
6703                 break;
6704         }
6705 }
6706
6707 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6708 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6709 /*
6710 ================
6711 R_SelectScene
6712 ================
6713 */
6714 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6715         if( scenetype != r_currentscenetype ) {
6716                 // store the old scenetype
6717                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6718                 r_currentscenetype = scenetype;
6719                 // move in the new scene
6720                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6721         }
6722 }
6723
6724 /*
6725 ================
6726 R_GetScenePointer
6727 ================
6728 */
6729 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6730 {
6731         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6732         if( scenetype == r_currentscenetype ) {
6733                 return &r_refdef.scene;
6734         } else {
6735                 return &r_scenes_store[ scenetype ];
6736         }
6737 }
6738
6739 int R_SortEntities_Compare(const void *ap, const void *bp)
6740 {
6741         const entity_render_t *a = *(const entity_render_t **)ap;
6742         const entity_render_t *b = *(const entity_render_t **)bp;
6743
6744         // 1. compare model
6745         if(a->model < b->model)
6746                 return -1;
6747         if(a->model > b->model)
6748                 return +1;
6749
6750         // 2. compare skin
6751         // TODO possibly calculate the REAL skinnum here first using
6752         // skinscenes?
6753         if(a->skinnum < b->skinnum)
6754                 return -1;
6755         if(a->skinnum > b->skinnum)
6756                 return +1;
6757
6758         // everything we compared is equal
6759         return 0;
6760 }
6761 void R_SortEntities(void)
6762 {
6763         // below or equal 2 ents, sorting never gains anything
6764         if(r_refdef.scene.numentities <= 2)
6765                 return;
6766         // sort
6767         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6768 }
6769
6770 /*
6771 ================
6772 R_RenderView
6773 ================
6774 */
6775 int dpsoftrast_test;
6776 extern void R_Shadow_UpdateBounceGridTexture(void);
6777 extern cvar_t r_shadow_bouncegrid;
6778 void R_RenderView(void)
6779 {
6780         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6781
6782         dpsoftrast_test = r_test.integer;
6783
6784         if (r_timereport_active)
6785                 R_TimeReport("start");
6786         r_textureframe++; // used only by R_GetCurrentTexture
6787         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6788
6789         if(R_CompileShader_CheckStaticParms())
6790                 R_GLSL_Restart_f();
6791
6792         if (!r_drawentities.integer)
6793                 r_refdef.scene.numentities = 0;
6794         else if (r_sortentities.integer)
6795                 R_SortEntities();
6796
6797         R_AnimCache_ClearCache();
6798         R_FrameData_NewFrame();
6799
6800         /* adjust for stereo display */
6801         if(R_Stereo_Active())
6802         {
6803                 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);
6804                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6805         }
6806
6807         if (r_refdef.view.isoverlay)
6808         {
6809                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6810                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6811                 R_TimeReport("depthclear");
6812
6813                 r_refdef.view.showdebug = false;
6814
6815                 r_waterstate.enabled = false;
6816                 r_waterstate.numwaterplanes = 0;
6817
6818                 R_RenderScene();
6819
6820                 r_refdef.view.matrix = originalmatrix;
6821
6822                 CHECKGLERROR
6823                 return;
6824         }
6825
6826         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6827         {
6828                 r_refdef.view.matrix = originalmatrix;
6829                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6830         }
6831
6832         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6833
6834         R_RenderView_UpdateViewVectors();
6835
6836         R_Shadow_UpdateWorldLightSelection();
6837
6838         R_Bloom_StartFrame();
6839         R_Water_StartFrame();
6840
6841         CHECKGLERROR
6842         if (r_timereport_active)
6843                 R_TimeReport("viewsetup");
6844
6845         R_ResetViewRendering3D();
6846
6847         if (r_refdef.view.clear || r_refdef.fogenabled)
6848         {
6849                 R_ClearScreen(r_refdef.fogenabled);
6850                 if (r_timereport_active)
6851                         R_TimeReport("viewclear");
6852         }
6853         r_refdef.view.clear = true;
6854
6855         // this produces a bloom texture to be used in R_BlendView() later
6856         if (r_bloomstate.hdr)
6857         {
6858                 R_HDR_RenderBloomTexture();
6859                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6860                 r_textureframe++; // used only by R_GetCurrentTexture
6861         }
6862
6863         r_refdef.view.showdebug = true;
6864
6865         R_View_Update();
6866         if (r_timereport_active)
6867                 R_TimeReport("visibility");
6868
6869         R_Shadow_UpdateBounceGridTexture();
6870         if (r_timereport_active && r_shadow_bouncegrid.integer)
6871                 R_TimeReport("bouncegrid");
6872
6873         r_waterstate.numwaterplanes = 0;
6874         if (r_waterstate.enabled)
6875                 R_RenderWaterPlanes();
6876
6877         R_RenderScene();
6878         r_waterstate.numwaterplanes = 0;
6879
6880         R_BlendView();
6881         if (r_timereport_active)
6882                 R_TimeReport("blendview");
6883
6884         GL_Scissor(0, 0, vid.width, vid.height);
6885         GL_ScissorTest(false);
6886
6887         r_refdef.view.matrix = originalmatrix;
6888
6889         CHECKGLERROR
6890 }
6891
6892 void R_RenderWaterPlanes(void)
6893 {
6894         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6895         {
6896                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6897                 if (r_timereport_active)
6898                         R_TimeReport("waterworld");
6899         }
6900
6901         // don't let sound skip if going slow
6902         if (r_refdef.scene.extraupdate)
6903                 S_ExtraUpdate ();
6904
6905         R_DrawModelsAddWaterPlanes();
6906         if (r_timereport_active)
6907                 R_TimeReport("watermodels");
6908
6909         if (r_waterstate.numwaterplanes)
6910         {
6911                 R_Water_ProcessPlanes();
6912                 if (r_timereport_active)
6913                         R_TimeReport("waterscenes");
6914         }
6915 }
6916
6917 extern void R_DrawLightningBeams (void);
6918 extern void VM_CL_AddPolygonsToMeshQueue (void);
6919 extern void R_DrawPortals (void);
6920 extern cvar_t cl_locs_show;
6921 static void R_DrawLocs(void);
6922 static void R_DrawEntityBBoxes(void);
6923 static void R_DrawModelDecals(void);
6924 extern void R_DrawModelShadows(void);
6925 extern void R_DrawModelShadowMaps(void);
6926 extern cvar_t cl_decals_newsystem;
6927 extern qboolean r_shadow_usingdeferredprepass;
6928 void R_RenderScene(void)
6929 {
6930         qboolean shadowmapping = false;
6931
6932         if (r_timereport_active)
6933                 R_TimeReport("beginscene");
6934
6935         r_refdef.stats.renders++;
6936
6937         R_UpdateFogColor();
6938
6939         // don't let sound skip if going slow
6940         if (r_refdef.scene.extraupdate)
6941                 S_ExtraUpdate ();
6942
6943         R_MeshQueue_BeginScene();
6944
6945         R_SkyStartFrame();
6946
6947         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);
6948
6949         if (r_timereport_active)
6950                 R_TimeReport("skystartframe");
6951
6952         if (cl.csqc_vidvars.drawworld)
6953         {
6954                 // don't let sound skip if going slow
6955                 if (r_refdef.scene.extraupdate)
6956                         S_ExtraUpdate ();
6957
6958                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6959                 {
6960                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6961                         if (r_timereport_active)
6962                                 R_TimeReport("worldsky");
6963                 }
6964
6965                 if (R_DrawBrushModelsSky() && r_timereport_active)
6966                         R_TimeReport("bmodelsky");
6967
6968                 if (skyrendermasked && skyrenderlater)
6969                 {
6970                         // we have to force off the water clipping plane while rendering sky
6971                         R_SetupView(false);
6972                         R_Sky();
6973                         R_SetupView(true);
6974                         if (r_timereport_active)
6975                                 R_TimeReport("sky");
6976                 }
6977         }
6978
6979         R_AnimCache_CacheVisibleEntities();
6980         if (r_timereport_active)
6981                 R_TimeReport("animation");
6982
6983         R_Shadow_PrepareLights();
6984         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6985                 R_Shadow_PrepareModelShadows();
6986         if (r_timereport_active)
6987                 R_TimeReport("preparelights");
6988
6989         if (R_Shadow_ShadowMappingEnabled())
6990                 shadowmapping = true;
6991
6992         if (r_shadow_usingdeferredprepass)
6993                 R_Shadow_DrawPrepass();
6994
6995         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6996         {
6997                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6998                 if (r_timereport_active)
6999                         R_TimeReport("worlddepth");
7000         }
7001         if (r_depthfirst.integer >= 2)
7002         {
7003                 R_DrawModelsDepth();
7004                 if (r_timereport_active)
7005                         R_TimeReport("modeldepth");
7006         }
7007
7008         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7009         {
7010                 R_DrawModelShadowMaps();
7011                 R_ResetViewRendering3D();
7012                 // don't let sound skip if going slow
7013                 if (r_refdef.scene.extraupdate)
7014                         S_ExtraUpdate ();
7015         }
7016
7017         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7018         {
7019                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7020                 if (r_timereport_active)
7021                         R_TimeReport("world");
7022         }
7023
7024         // don't let sound skip if going slow
7025         if (r_refdef.scene.extraupdate)
7026                 S_ExtraUpdate ();
7027
7028         R_DrawModels();
7029         if (r_timereport_active)
7030                 R_TimeReport("models");
7031
7032         // don't let sound skip if going slow
7033         if (r_refdef.scene.extraupdate)
7034                 S_ExtraUpdate ();
7035
7036         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7037         {
7038                 R_DrawModelShadows();
7039                 R_ResetViewRendering3D();
7040                 // don't let sound skip if going slow
7041                 if (r_refdef.scene.extraupdate)
7042                         S_ExtraUpdate ();
7043         }
7044
7045         if (!r_shadow_usingdeferredprepass)
7046         {
7047                 R_Shadow_DrawLights();
7048                 if (r_timereport_active)
7049                         R_TimeReport("rtlights");
7050         }
7051
7052         // don't let sound skip if going slow
7053         if (r_refdef.scene.extraupdate)
7054                 S_ExtraUpdate ();
7055
7056         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7057         {
7058                 R_DrawModelShadows();
7059                 R_ResetViewRendering3D();
7060                 // don't let sound skip if going slow
7061                 if (r_refdef.scene.extraupdate)
7062                         S_ExtraUpdate ();
7063         }
7064
7065         if (cl.csqc_vidvars.drawworld)
7066         {
7067                 if (cl_decals_newsystem.integer)
7068                 {
7069                         R_DrawModelDecals();
7070                         if (r_timereport_active)
7071                                 R_TimeReport("modeldecals");
7072                 }
7073                 else
7074                 {
7075                         R_DrawDecals();
7076                         if (r_timereport_active)
7077                                 R_TimeReport("decals");
7078                 }
7079
7080                 R_DrawParticles();
7081                 if (r_timereport_active)
7082                         R_TimeReport("particles");
7083
7084                 R_DrawExplosions();
7085                 if (r_timereport_active)
7086                         R_TimeReport("explosions");
7087
7088                 R_DrawLightningBeams();
7089                 if (r_timereport_active)
7090                         R_TimeReport("lightning");
7091         }
7092
7093         VM_CL_AddPolygonsToMeshQueue();
7094
7095         if (r_refdef.view.showdebug)
7096         {
7097                 if (cl_locs_show.integer)
7098                 {
7099                         R_DrawLocs();
7100                         if (r_timereport_active)
7101                                 R_TimeReport("showlocs");
7102                 }
7103
7104                 if (r_drawportals.integer)
7105                 {
7106                         R_DrawPortals();
7107                         if (r_timereport_active)
7108                                 R_TimeReport("portals");
7109                 }
7110
7111                 if (r_showbboxes.value > 0)
7112                 {
7113                         R_DrawEntityBBoxes();
7114                         if (r_timereport_active)
7115                                 R_TimeReport("bboxes");
7116                 }
7117         }
7118
7119         if (r_transparent.integer)
7120         {
7121                 R_MeshQueue_RenderTransparent();
7122                 if (r_timereport_active)
7123                         R_TimeReport("drawtrans");
7124         }
7125
7126         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))
7127         {
7128                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7129                 if (r_timereport_active)
7130                         R_TimeReport("worlddebug");
7131                 R_DrawModelsDebug();
7132                 if (r_timereport_active)
7133                         R_TimeReport("modeldebug");
7134         }
7135
7136         if (cl.csqc_vidvars.drawworld)
7137         {
7138                 R_Shadow_DrawCoronas();
7139                 if (r_timereport_active)
7140                         R_TimeReport("coronas");
7141         }
7142
7143 #if 0
7144         {
7145                 GL_DepthTest(false);
7146                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7147                 GL_Color(1, 1, 1, 1);
7148                 qglBegin(GL_POLYGON);
7149                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7150                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7151                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7152                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7153                 qglEnd();
7154                 qglBegin(GL_POLYGON);
7155                 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]);
7156                 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]);
7157                 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]);
7158                 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]);
7159                 qglEnd();
7160                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7161         }
7162 #endif
7163
7164         // don't let sound skip if going slow
7165         if (r_refdef.scene.extraupdate)
7166                 S_ExtraUpdate ();
7167
7168         R_ResetViewRendering2D();
7169 }
7170
7171 static const unsigned short bboxelements[36] =
7172 {
7173         5, 1, 3, 5, 3, 7,
7174         6, 2, 0, 6, 0, 4,
7175         7, 3, 2, 7, 2, 6,
7176         4, 0, 1, 4, 1, 5,
7177         4, 5, 7, 4, 7, 6,
7178         1, 0, 2, 1, 2, 3,
7179 };
7180
7181 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7182 {
7183         int i;
7184         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7185
7186         RSurf_ActiveWorldEntity();
7187
7188         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7189         GL_DepthMask(false);
7190         GL_DepthRange(0, 1);
7191         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7192 //      R_Mesh_ResetTextureState();
7193
7194         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7195         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7196         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7197         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7198         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7199         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7200         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7201         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7202         R_FillColors(color4f, 8, cr, cg, cb, ca);
7203         if (r_refdef.fogenabled)
7204         {
7205                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7206                 {
7207                         f1 = RSurf_FogVertex(v);
7208                         f2 = 1 - f1;
7209                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7210                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7211                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7212                 }
7213         }
7214         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7215         R_Mesh_ResetTextureState();
7216         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7217         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7218 }
7219
7220 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7221 {
7222         int i;
7223         float color[4];
7224         prvm_edict_t *edict;
7225         prvm_prog_t *prog_save = prog;
7226
7227         // this function draws bounding boxes of server entities
7228         if (!sv.active)
7229                 return;
7230
7231         GL_CullFace(GL_NONE);
7232         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7233
7234         prog = 0;
7235         SV_VM_Begin();
7236         for (i = 0;i < numsurfaces;i++)
7237         {
7238                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7239                 switch ((int)PRVM_serveredictfloat(edict, solid))
7240                 {
7241                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7242                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7243                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7244                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7245                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7246                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7247                 }
7248                 color[3] *= r_showbboxes.value;
7249                 color[3] = bound(0, color[3], 1);
7250                 GL_DepthTest(!r_showdisabledepthtest.integer);
7251                 GL_CullFace(r_refdef.view.cullface_front);
7252                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7253         }
7254         SV_VM_End();
7255         prog = prog_save;
7256 }
7257
7258 static void R_DrawEntityBBoxes(void)
7259 {
7260         int i;
7261         prvm_edict_t *edict;
7262         vec3_t center;
7263         prvm_prog_t *prog_save = prog;
7264
7265         // this function draws bounding boxes of server entities
7266         if (!sv.active)
7267                 return;
7268
7269         prog = 0;
7270         SV_VM_Begin();
7271         for (i = 0;i < prog->num_edicts;i++)
7272         {
7273                 edict = PRVM_EDICT_NUM(i);
7274                 if (edict->priv.server->free)
7275                         continue;
7276                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7277                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7278                         continue;
7279                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7280                         continue;
7281                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7282                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7283         }
7284         SV_VM_End();
7285         prog = prog_save;
7286 }
7287
7288 static const int nomodelelement3i[24] =
7289 {
7290         5, 2, 0,
7291         5, 1, 2,
7292         5, 0, 3,
7293         5, 3, 1,
7294         0, 2, 4,
7295         2, 1, 4,
7296         3, 0, 4,
7297         1, 3, 4
7298 };
7299
7300 static const unsigned short nomodelelement3s[24] =
7301 {
7302         5, 2, 0,
7303         5, 1, 2,
7304         5, 0, 3,
7305         5, 3, 1,
7306         0, 2, 4,
7307         2, 1, 4,
7308         3, 0, 4,
7309         1, 3, 4
7310 };
7311
7312 static const float nomodelvertex3f[6*3] =
7313 {
7314         -16,   0,   0,
7315          16,   0,   0,
7316           0, -16,   0,
7317           0,  16,   0,
7318           0,   0, -16,
7319           0,   0,  16
7320 };
7321
7322 static const float nomodelcolor4f[6*4] =
7323 {
7324         0.0f, 0.0f, 0.5f, 1.0f,
7325         0.0f, 0.0f, 0.5f, 1.0f,
7326         0.0f, 0.5f, 0.0f, 1.0f,
7327         0.0f, 0.5f, 0.0f, 1.0f,
7328         0.5f, 0.0f, 0.0f, 1.0f,
7329         0.5f, 0.0f, 0.0f, 1.0f
7330 };
7331
7332 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7333 {
7334         int i;
7335         float f1, f2, *c;
7336         float color4f[6*4];
7337
7338         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);
7339
7340         // this is only called once per entity so numsurfaces is always 1, and
7341         // surfacelist is always {0}, so this code does not handle batches
7342
7343         if (rsurface.ent_flags & RENDER_ADDITIVE)
7344         {
7345                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7346                 GL_DepthMask(false);
7347         }
7348         else if (rsurface.colormod[3] < 1)
7349         {
7350                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7351                 GL_DepthMask(false);
7352         }
7353         else
7354         {
7355                 GL_BlendFunc(GL_ONE, GL_ZERO);
7356                 GL_DepthMask(true);
7357         }
7358         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7359         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7360         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7361         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7362         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7363         for (i = 0, c = color4f;i < 6;i++, c += 4)
7364         {
7365                 c[0] *= rsurface.colormod[0];
7366                 c[1] *= rsurface.colormod[1];
7367                 c[2] *= rsurface.colormod[2];
7368                 c[3] *= rsurface.colormod[3];
7369         }
7370         if (r_refdef.fogenabled)
7371         {
7372                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7373                 {
7374                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7375                         f2 = 1 - f1;
7376                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7377                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7378                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7379                 }
7380         }
7381 //      R_Mesh_ResetTextureState();
7382         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7383         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7384         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7385 }
7386
7387 void R_DrawNoModel(entity_render_t *ent)
7388 {
7389         vec3_t org;
7390         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7391         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7392                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7393         else
7394                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7395 }
7396
7397 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7398 {
7399         vec3_t right1, right2, diff, normal;
7400
7401         VectorSubtract (org2, org1, normal);
7402
7403         // calculate 'right' vector for start
7404         VectorSubtract (r_refdef.view.origin, org1, diff);
7405         CrossProduct (normal, diff, right1);
7406         VectorNormalize (right1);
7407
7408         // calculate 'right' vector for end
7409         VectorSubtract (r_refdef.view.origin, org2, diff);
7410         CrossProduct (normal, diff, right2);
7411         VectorNormalize (right2);
7412
7413         vert[ 0] = org1[0] + width * right1[0];
7414         vert[ 1] = org1[1] + width * right1[1];
7415         vert[ 2] = org1[2] + width * right1[2];
7416         vert[ 3] = org1[0] - width * right1[0];
7417         vert[ 4] = org1[1] - width * right1[1];
7418         vert[ 5] = org1[2] - width * right1[2];
7419         vert[ 6] = org2[0] - width * right2[0];
7420         vert[ 7] = org2[1] - width * right2[1];
7421         vert[ 8] = org2[2] - width * right2[2];
7422         vert[ 9] = org2[0] + width * right2[0];
7423         vert[10] = org2[1] + width * right2[1];
7424         vert[11] = org2[2] + width * right2[2];
7425 }
7426
7427 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)
7428 {
7429         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7430         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7431         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7432         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7433         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7434         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7435         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7436         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7437         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7438         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7439         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7440         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7441 }
7442
7443 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7444 {
7445         int i;
7446         float *vertex3f;
7447         float v[3];
7448         VectorSet(v, x, y, z);
7449         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7450                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7451                         break;
7452         if (i == mesh->numvertices)
7453         {
7454                 if (mesh->numvertices < mesh->maxvertices)
7455                 {
7456                         VectorCopy(v, vertex3f);
7457                         mesh->numvertices++;
7458                 }
7459                 return mesh->numvertices;
7460         }
7461         else
7462                 return i;
7463 }
7464
7465 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7466 {
7467         int i;
7468         int *e, element[3];
7469         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7470         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7471         e = mesh->element3i + mesh->numtriangles * 3;
7472         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7473         {
7474                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7475                 if (mesh->numtriangles < mesh->maxtriangles)
7476                 {
7477                         *e++ = element[0];
7478                         *e++ = element[1];
7479                         *e++ = element[2];
7480                         mesh->numtriangles++;
7481                 }
7482                 element[1] = element[2];
7483         }
7484 }
7485
7486 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7487 {
7488         int i;
7489         int *e, element[3];
7490         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7491         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7492         e = mesh->element3i + mesh->numtriangles * 3;
7493         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7494         {
7495                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7496                 if (mesh->numtriangles < mesh->maxtriangles)
7497                 {
7498                         *e++ = element[0];
7499                         *e++ = element[1];
7500                         *e++ = element[2];
7501                         mesh->numtriangles++;
7502                 }
7503                 element[1] = element[2];
7504         }
7505 }
7506
7507 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7508 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7509 {
7510         int planenum, planenum2;
7511         int w;
7512         int tempnumpoints;
7513         mplane_t *plane, *plane2;
7514         double maxdist;
7515         double temppoints[2][256*3];
7516         // figure out how large a bounding box we need to properly compute this brush
7517         maxdist = 0;
7518         for (w = 0;w < numplanes;w++)
7519                 maxdist = max(maxdist, fabs(planes[w].dist));
7520         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7521         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7522         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7523         {
7524                 w = 0;
7525                 tempnumpoints = 4;
7526                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7527                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7528                 {
7529                         if (planenum2 == planenum)
7530                                 continue;
7531                         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);
7532                         w = !w;
7533                 }
7534                 if (tempnumpoints < 3)
7535                         continue;
7536                 // generate elements forming a triangle fan for this polygon
7537                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7538         }
7539 }
7540
7541 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)
7542 {
7543         texturelayer_t *layer;
7544         layer = t->currentlayers + t->currentnumlayers++;
7545         layer->type = type;
7546         layer->depthmask = depthmask;
7547         layer->blendfunc1 = blendfunc1;
7548         layer->blendfunc2 = blendfunc2;
7549         layer->texture = texture;
7550         layer->texmatrix = *matrix;
7551         layer->color[0] = r;
7552         layer->color[1] = g;
7553         layer->color[2] = b;
7554         layer->color[3] = a;
7555 }
7556
7557 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7558 {
7559         if(parms[0] == 0 && parms[1] == 0)
7560                 return false;
7561         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7562                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7563                         return false;
7564         return true;
7565 }
7566
7567 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7568 {
7569         double index, f;
7570         index = parms[2] + rsurface.shadertime * parms[3];
7571         index -= floor(index);
7572         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7573         {
7574         default:
7575         case Q3WAVEFUNC_NONE:
7576         case Q3WAVEFUNC_NOISE:
7577         case Q3WAVEFUNC_COUNT:
7578                 f = 0;
7579                 break;
7580         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7581         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7582         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7583         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7584         case Q3WAVEFUNC_TRIANGLE:
7585                 index *= 4;
7586                 f = index - floor(index);
7587                 if (index < 1)
7588                 {
7589                         // f = f;
7590                 }
7591                 else if (index < 2)
7592                         f = 1 - f;
7593                 else if (index < 3)
7594                         f = -f;
7595                 else
7596                         f = -(1 - f);
7597                 break;
7598         }
7599         f = parms[0] + parms[1] * f;
7600         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7601                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7602         return (float) f;
7603 }
7604
7605 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7606 {
7607         int w, h, idx;
7608         double f;
7609         double offsetd[2];
7610         float tcmat[12];
7611         matrix4x4_t matrix, temp;
7612         switch(tcmod->tcmod)
7613         {
7614                 case Q3TCMOD_COUNT:
7615                 case Q3TCMOD_NONE:
7616                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7617                                 matrix = r_waterscrollmatrix;
7618                         else
7619                                 matrix = identitymatrix;
7620                         break;
7621                 case Q3TCMOD_ENTITYTRANSLATE:
7622                         // this is used in Q3 to allow the gamecode to control texcoord
7623                         // scrolling on the entity, which is not supported in darkplaces yet.
7624                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7625                         break;
7626                 case Q3TCMOD_ROTATE:
7627                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7628                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7629                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7630                         break;
7631                 case Q3TCMOD_SCALE:
7632                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7633                         break;
7634                 case Q3TCMOD_SCROLL:
7635                         // extra care is needed because of precision breakdown with large values of time
7636                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7637                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7638                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7639                         break;
7640                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7641                         w = (int) tcmod->parms[0];
7642                         h = (int) tcmod->parms[1];
7643                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7644                         f = f - floor(f);
7645                         idx = (int) floor(f * w * h);
7646                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7647                         break;
7648                 case Q3TCMOD_STRETCH:
7649                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7650                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7651                         break;
7652                 case Q3TCMOD_TRANSFORM:
7653                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7654                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7655                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7656                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7657                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7658                         break;
7659                 case Q3TCMOD_TURBULENT:
7660                         // this is handled in the RSurf_PrepareVertices function
7661                         matrix = identitymatrix;
7662                         break;
7663         }
7664         temp = *texmatrix;
7665         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7666 }
7667
7668 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7669 {
7670         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7671         char name[MAX_QPATH];
7672         skinframe_t *skinframe;
7673         unsigned char pixels[296*194];
7674         strlcpy(cache->name, skinname, sizeof(cache->name));
7675         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7676         if (developer_loading.integer)
7677                 Con_Printf("loading %s\n", name);
7678         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7679         if (!skinframe || !skinframe->base)
7680         {
7681                 unsigned char *f;
7682                 fs_offset_t filesize;
7683                 skinframe = NULL;
7684                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7685                 if (f)
7686                 {
7687                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7688                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7689                         Mem_Free(f);
7690                 }
7691         }
7692         cache->skinframe = skinframe;
7693 }
7694
7695 texture_t *R_GetCurrentTexture(texture_t *t)
7696 {
7697         int i;
7698         const entity_render_t *ent = rsurface.entity;
7699         dp_model_t *model = ent->model;
7700         q3shaderinfo_layer_tcmod_t *tcmod;
7701
7702         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7703                 return t->currentframe;
7704         t->update_lastrenderframe = r_textureframe;
7705         t->update_lastrenderentity = (void *)ent;
7706
7707         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7708                 t->camera_entity = ent->entitynumber;
7709         else
7710                 t->camera_entity = 0;
7711
7712         // switch to an alternate material if this is a q1bsp animated material
7713         {
7714                 texture_t *texture = t;
7715                 int s = rsurface.ent_skinnum;
7716                 if ((unsigned int)s >= (unsigned int)model->numskins)
7717                         s = 0;
7718                 if (model->skinscenes)
7719                 {
7720                         if (model->skinscenes[s].framecount > 1)
7721                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7722                         else
7723                                 s = model->skinscenes[s].firstframe;
7724                 }
7725                 if (s > 0)
7726                         t = t + s * model->num_surfaces;
7727                 if (t->animated)
7728                 {
7729                         // use an alternate animation if the entity's frame is not 0,
7730                         // and only if the texture has an alternate animation
7731                         if (rsurface.ent_alttextures && t->anim_total[1])
7732                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7733                         else
7734                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7735                 }
7736                 texture->currentframe = t;
7737         }
7738
7739         // update currentskinframe to be a qw skin or animation frame
7740         if (rsurface.ent_qwskin >= 0)
7741         {
7742                 i = rsurface.ent_qwskin;
7743                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7744                 {
7745                         r_qwskincache_size = cl.maxclients;
7746                         if (r_qwskincache)
7747                                 Mem_Free(r_qwskincache);
7748                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7749                 }
7750                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7751                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7752                 t->currentskinframe = r_qwskincache[i].skinframe;
7753                 if (t->currentskinframe == NULL)
7754                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7755         }
7756         else if (t->numskinframes >= 2)
7757                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7758         if (t->backgroundnumskinframes >= 2)
7759                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7760
7761         t->currentmaterialflags = t->basematerialflags;
7762         t->currentalpha = rsurface.colormod[3];
7763         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7764                 t->currentalpha *= r_wateralpha.value;
7765         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7766                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7767         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7768                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7769         if (!(rsurface.ent_flags & RENDER_LIGHT))
7770                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7771         else if (FAKELIGHT_ENABLED)
7772         {
7773                 // no modellight if using fakelight for the map
7774         }
7775         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7776         {
7777                 // pick a model lighting mode
7778                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7779                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7780                 else
7781                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7782         }
7783         if (rsurface.ent_flags & RENDER_ADDITIVE)
7784                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7785         else if (t->currentalpha < 1)
7786                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7787         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7788                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7789         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7790                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7791         if (t->backgroundnumskinframes)
7792                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7793         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7794         {
7795                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7796                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7797         }
7798         else
7799                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7800         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7801         {
7802                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7803                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7804         }
7805         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7806                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7807
7808         // there is no tcmod
7809         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7810         {
7811                 t->currenttexmatrix = r_waterscrollmatrix;
7812                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7813         }
7814         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7815         {
7816                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7817                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7818         }
7819
7820         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7821                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7822         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7823                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7824
7825         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7826         if (t->currentskinframe->qpixels)
7827                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7828         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7829         if (!t->basetexture)
7830                 t->basetexture = r_texture_notexture;
7831         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7832         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7833         t->nmaptexture = t->currentskinframe->nmap;
7834         if (!t->nmaptexture)
7835                 t->nmaptexture = r_texture_blanknormalmap;
7836         t->glosstexture = r_texture_black;
7837         t->glowtexture = t->currentskinframe->glow;
7838         t->fogtexture = t->currentskinframe->fog;
7839         t->reflectmasktexture = t->currentskinframe->reflect;
7840         if (t->backgroundnumskinframes)
7841         {
7842                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7843                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7844                 t->backgroundglosstexture = r_texture_black;
7845                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7846                 if (!t->backgroundnmaptexture)
7847                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7848         }
7849         else
7850         {
7851                 t->backgroundbasetexture = r_texture_white;
7852                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7853                 t->backgroundglosstexture = r_texture_black;
7854                 t->backgroundglowtexture = NULL;
7855         }
7856         t->specularpower = r_shadow_glossexponent.value;
7857         // TODO: store reference values for these in the texture?
7858         t->specularscale = 0;
7859         if (r_shadow_gloss.integer > 0)
7860         {
7861                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7862                 {
7863                         if (r_shadow_glossintensity.value > 0)
7864                         {
7865                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7866                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7867                                 t->specularscale = r_shadow_glossintensity.value;
7868                         }
7869                 }
7870                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7871                 {
7872                         t->glosstexture = r_texture_white;
7873                         t->backgroundglosstexture = r_texture_white;
7874                         t->specularscale = r_shadow_gloss2intensity.value;
7875                         t->specularpower = r_shadow_gloss2exponent.value;
7876                 }
7877         }
7878         t->specularscale *= t->specularscalemod;
7879         t->specularpower *= t->specularpowermod;
7880         t->rtlightambient = 0;
7881
7882         // lightmaps mode looks bad with dlights using actual texturing, so turn
7883         // off the colormap and glossmap, but leave the normalmap on as it still
7884         // accurately represents the shading involved
7885         if (gl_lightmaps.integer)
7886         {
7887                 t->basetexture = r_texture_grey128;
7888                 t->pantstexture = r_texture_black;
7889                 t->shirttexture = r_texture_black;
7890                 t->nmaptexture = r_texture_blanknormalmap;
7891                 t->glosstexture = r_texture_black;
7892                 t->glowtexture = NULL;
7893                 t->fogtexture = NULL;
7894                 t->reflectmasktexture = NULL;
7895                 t->backgroundbasetexture = NULL;
7896                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7897                 t->backgroundglosstexture = r_texture_black;
7898                 t->backgroundglowtexture = NULL;
7899                 t->specularscale = 0;
7900                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7901         }
7902
7903         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7904         VectorClear(t->dlightcolor);
7905         t->currentnumlayers = 0;
7906         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7907         {
7908                 int blendfunc1, blendfunc2;
7909                 qboolean depthmask;
7910                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7911                 {
7912                         blendfunc1 = GL_SRC_ALPHA;
7913                         blendfunc2 = GL_ONE;
7914                 }
7915                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7916                 {
7917                         blendfunc1 = GL_SRC_ALPHA;
7918                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7919                 }
7920                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7921                 {
7922                         blendfunc1 = t->customblendfunc[0];
7923                         blendfunc2 = t->customblendfunc[1];
7924                 }
7925                 else
7926                 {
7927                         blendfunc1 = GL_ONE;
7928                         blendfunc2 = GL_ZERO;
7929                 }
7930                 // don't colormod evilblend textures
7931                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7932                         VectorSet(t->lightmapcolor, 1, 1, 1);
7933                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7934                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7935                 {
7936                         // fullbright is not affected by r_refdef.lightmapintensity
7937                         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]);
7938                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7939                                 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]);
7940                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7941                                 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]);
7942                 }
7943                 else
7944                 {
7945                         vec3_t ambientcolor;
7946                         float colorscale;
7947                         // set the color tint used for lights affecting this surface
7948                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7949                         colorscale = 2;
7950                         // q3bsp has no lightmap updates, so the lightstylevalue that
7951                         // would normally be baked into the lightmap must be
7952                         // applied to the color
7953                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7954                         if (model->type == mod_brushq3)
7955                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7956                         colorscale *= r_refdef.lightmapintensity;
7957                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7958                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7959                         // basic lit geometry
7960                         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]);
7961                         // add pants/shirt if needed
7962                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7963                                 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]);
7964                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7965                                 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]);
7966                         // now add ambient passes if needed
7967                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7968                         {
7969                                 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]);
7970                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7971                                         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]);
7972                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7973                                         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]);
7974                         }
7975                 }
7976                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7977                         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]);
7978                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7979                 {
7980                         // if this is opaque use alpha blend which will darken the earlier
7981                         // passes cheaply.
7982                         //
7983                         // if this is an alpha blended material, all the earlier passes
7984                         // were darkened by fog already, so we only need to add the fog
7985                         // color ontop through the fog mask texture
7986                         //
7987                         // if this is an additive blended material, all the earlier passes
7988                         // were darkened by fog already, and we should not add fog color
7989                         // (because the background was not darkened, there is no fog color
7990                         // that was lost behind it).
7991                         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]);
7992                 }
7993         }
7994
7995         return t->currentframe;
7996 }
7997
7998 rsurfacestate_t rsurface;
7999
8000 void RSurf_ActiveWorldEntity(void)
8001 {
8002         dp_model_t *model = r_refdef.scene.worldmodel;
8003         //if (rsurface.entity == r_refdef.scene.worldentity)
8004         //      return;
8005         rsurface.entity = r_refdef.scene.worldentity;
8006         rsurface.skeleton = NULL;
8007         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8008         rsurface.ent_skinnum = 0;
8009         rsurface.ent_qwskin = -1;
8010         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8011         rsurface.shadertime = r_refdef.scene.time;
8012         rsurface.matrix = identitymatrix;
8013         rsurface.inversematrix = identitymatrix;
8014         rsurface.matrixscale = 1;
8015         rsurface.inversematrixscale = 1;
8016         R_EntityMatrix(&identitymatrix);
8017         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8018         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8019         rsurface.fograngerecip = r_refdef.fograngerecip;
8020         rsurface.fogheightfade = r_refdef.fogheightfade;
8021         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8022         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8023         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8024         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8025         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8026         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8027         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8028         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8029         rsurface.colormod[3] = 1;
8030         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);
8031         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8032         rsurface.frameblend[0].lerp = 1;
8033         rsurface.ent_alttextures = false;
8034         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8035         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8036         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8037         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8038         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8039         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8040         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8041         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8042         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8043         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8044         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8045         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8046         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8047         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8048         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8049         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8050         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8051         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8052         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8053         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8054         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8055         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8056         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8057         rsurface.modelelement3i = model->surfmesh.data_element3i;
8058         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8059         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8060         rsurface.modelelement3s = model->surfmesh.data_element3s;
8061         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8062         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8063         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8064         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8065         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8066         rsurface.modelsurfaces = model->data_surfaces;
8067         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8068         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8069         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8070         rsurface.modelgeneratedvertex = false;
8071         rsurface.batchgeneratedvertex = false;
8072         rsurface.batchfirstvertex = 0;
8073         rsurface.batchnumvertices = 0;
8074         rsurface.batchfirsttriangle = 0;
8075         rsurface.batchnumtriangles = 0;
8076         rsurface.batchvertex3f  = NULL;
8077         rsurface.batchvertex3f_vertexbuffer = NULL;
8078         rsurface.batchvertex3f_bufferoffset = 0;
8079         rsurface.batchsvector3f = NULL;
8080         rsurface.batchsvector3f_vertexbuffer = NULL;
8081         rsurface.batchsvector3f_bufferoffset = 0;
8082         rsurface.batchtvector3f = NULL;
8083         rsurface.batchtvector3f_vertexbuffer = NULL;
8084         rsurface.batchtvector3f_bufferoffset = 0;
8085         rsurface.batchnormal3f  = NULL;
8086         rsurface.batchnormal3f_vertexbuffer = NULL;
8087         rsurface.batchnormal3f_bufferoffset = 0;
8088         rsurface.batchlightmapcolor4f = NULL;
8089         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8090         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8091         rsurface.batchtexcoordtexture2f = NULL;
8092         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8093         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8094         rsurface.batchtexcoordlightmap2f = NULL;
8095         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8096         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8097         rsurface.batchvertexmesh = NULL;
8098         rsurface.batchvertexmeshbuffer = NULL;
8099         rsurface.batchvertex3fbuffer = NULL;
8100         rsurface.batchelement3i = NULL;
8101         rsurface.batchelement3i_indexbuffer = NULL;
8102         rsurface.batchelement3i_bufferoffset = 0;
8103         rsurface.batchelement3s = NULL;
8104         rsurface.batchelement3s_indexbuffer = NULL;
8105         rsurface.batchelement3s_bufferoffset = 0;
8106         rsurface.passcolor4f = NULL;
8107         rsurface.passcolor4f_vertexbuffer = NULL;
8108         rsurface.passcolor4f_bufferoffset = 0;
8109 }
8110
8111 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8112 {
8113         dp_model_t *model = ent->model;
8114         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8115         //      return;
8116         rsurface.entity = (entity_render_t *)ent;
8117         rsurface.skeleton = ent->skeleton;
8118         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8119         rsurface.ent_skinnum = ent->skinnum;
8120         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;
8121         rsurface.ent_flags = ent->flags;
8122         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8123         rsurface.matrix = ent->matrix;
8124         rsurface.inversematrix = ent->inversematrix;
8125         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8126         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8127         R_EntityMatrix(&rsurface.matrix);
8128         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8129         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8130         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8131         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8132         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8133         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8134         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8135         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8136         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8137         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8138         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8139         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8140         rsurface.colormod[3] = ent->alpha;
8141         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8142         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8143         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8144         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8145         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8146         if (ent->model->brush.submodel && !prepass)
8147         {
8148                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8149                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8150         }
8151         if (model->surfmesh.isanimated && model->AnimateVertices)
8152         {
8153                 if (ent->animcache_vertex3f)
8154                 {
8155                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8156                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8157                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8158                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8159                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8160                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8161                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8162                 }
8163                 else if (wanttangents)
8164                 {
8165                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8166                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8167                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8168                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8169                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8170                         rsurface.modelvertexmesh = NULL;
8171                         rsurface.modelvertexmeshbuffer = NULL;
8172                         rsurface.modelvertex3fbuffer = NULL;
8173                 }
8174                 else if (wantnormals)
8175                 {
8176                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8177                         rsurface.modelsvector3f = NULL;
8178                         rsurface.modeltvector3f = NULL;
8179                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8180                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8181                         rsurface.modelvertexmesh = NULL;
8182                         rsurface.modelvertexmeshbuffer = NULL;
8183                         rsurface.modelvertex3fbuffer = NULL;
8184                 }
8185                 else
8186                 {
8187                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8188                         rsurface.modelsvector3f = NULL;
8189                         rsurface.modeltvector3f = NULL;
8190                         rsurface.modelnormal3f = NULL;
8191                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8192                         rsurface.modelvertexmesh = NULL;
8193                         rsurface.modelvertexmeshbuffer = NULL;
8194                         rsurface.modelvertex3fbuffer = NULL;
8195                 }
8196                 rsurface.modelvertex3f_vertexbuffer = 0;
8197                 rsurface.modelvertex3f_bufferoffset = 0;
8198                 rsurface.modelsvector3f_vertexbuffer = 0;
8199                 rsurface.modelsvector3f_bufferoffset = 0;
8200                 rsurface.modeltvector3f_vertexbuffer = 0;
8201                 rsurface.modeltvector3f_bufferoffset = 0;
8202                 rsurface.modelnormal3f_vertexbuffer = 0;
8203                 rsurface.modelnormal3f_bufferoffset = 0;
8204                 rsurface.modelgeneratedvertex = true;
8205         }
8206         else
8207         {
8208                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8209                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8210                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8211                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8212                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8213                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8214                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8215                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8216                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8217                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8218                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8219                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8220                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8221                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8222                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8223                 rsurface.modelgeneratedvertex = false;
8224         }
8225         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8226         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8227         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8228         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8229         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8230         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8231         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8232         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8233         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8234         rsurface.modelelement3i = model->surfmesh.data_element3i;
8235         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8236         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8237         rsurface.modelelement3s = model->surfmesh.data_element3s;
8238         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8239         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8240         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8241         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8242         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8243         rsurface.modelsurfaces = model->data_surfaces;
8244         rsurface.batchgeneratedvertex = false;
8245         rsurface.batchfirstvertex = 0;
8246         rsurface.batchnumvertices = 0;
8247         rsurface.batchfirsttriangle = 0;
8248         rsurface.batchnumtriangles = 0;
8249         rsurface.batchvertex3f  = NULL;
8250         rsurface.batchvertex3f_vertexbuffer = NULL;
8251         rsurface.batchvertex3f_bufferoffset = 0;
8252         rsurface.batchsvector3f = NULL;
8253         rsurface.batchsvector3f_vertexbuffer = NULL;
8254         rsurface.batchsvector3f_bufferoffset = 0;
8255         rsurface.batchtvector3f = NULL;
8256         rsurface.batchtvector3f_vertexbuffer = NULL;
8257         rsurface.batchtvector3f_bufferoffset = 0;
8258         rsurface.batchnormal3f  = NULL;
8259         rsurface.batchnormal3f_vertexbuffer = NULL;
8260         rsurface.batchnormal3f_bufferoffset = 0;
8261         rsurface.batchlightmapcolor4f = NULL;
8262         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8263         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8264         rsurface.batchtexcoordtexture2f = NULL;
8265         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8266         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8267         rsurface.batchtexcoordlightmap2f = NULL;
8268         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8269         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8270         rsurface.batchvertexmesh = NULL;
8271         rsurface.batchvertexmeshbuffer = NULL;
8272         rsurface.batchvertex3fbuffer = NULL;
8273         rsurface.batchelement3i = NULL;
8274         rsurface.batchelement3i_indexbuffer = NULL;
8275         rsurface.batchelement3i_bufferoffset = 0;
8276         rsurface.batchelement3s = NULL;
8277         rsurface.batchelement3s_indexbuffer = NULL;
8278         rsurface.batchelement3s_bufferoffset = 0;
8279         rsurface.passcolor4f = NULL;
8280         rsurface.passcolor4f_vertexbuffer = NULL;
8281         rsurface.passcolor4f_bufferoffset = 0;
8282 }
8283
8284 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)
8285 {
8286         rsurface.entity = r_refdef.scene.worldentity;
8287         rsurface.skeleton = NULL;
8288         rsurface.ent_skinnum = 0;
8289         rsurface.ent_qwskin = -1;
8290         rsurface.ent_flags = entflags;
8291         rsurface.shadertime = r_refdef.scene.time - shadertime;
8292         rsurface.modelnumvertices = numvertices;
8293         rsurface.modelnumtriangles = numtriangles;
8294         rsurface.matrix = *matrix;
8295         rsurface.inversematrix = *inversematrix;
8296         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8297         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8298         R_EntityMatrix(&rsurface.matrix);
8299         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8300         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8301         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8302         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8303         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8304         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8305         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8306         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8307         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8308         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8309         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8310         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8311         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);
8312         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8313         rsurface.frameblend[0].lerp = 1;
8314         rsurface.ent_alttextures = false;
8315         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8316         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8317         if (wanttangents)
8318         {
8319                 rsurface.modelvertex3f = (float *)vertex3f;
8320                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8321                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8322                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8323         }
8324         else if (wantnormals)
8325         {
8326                 rsurface.modelvertex3f = (float *)vertex3f;
8327                 rsurface.modelsvector3f = NULL;
8328                 rsurface.modeltvector3f = NULL;
8329                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8330         }
8331         else
8332         {
8333                 rsurface.modelvertex3f = (float *)vertex3f;
8334                 rsurface.modelsvector3f = NULL;
8335                 rsurface.modeltvector3f = NULL;
8336                 rsurface.modelnormal3f = NULL;
8337         }
8338         rsurface.modelvertexmesh = NULL;
8339         rsurface.modelvertexmeshbuffer = NULL;
8340         rsurface.modelvertex3fbuffer = NULL;
8341         rsurface.modelvertex3f_vertexbuffer = 0;
8342         rsurface.modelvertex3f_bufferoffset = 0;
8343         rsurface.modelsvector3f_vertexbuffer = 0;
8344         rsurface.modelsvector3f_bufferoffset = 0;
8345         rsurface.modeltvector3f_vertexbuffer = 0;
8346         rsurface.modeltvector3f_bufferoffset = 0;
8347         rsurface.modelnormal3f_vertexbuffer = 0;
8348         rsurface.modelnormal3f_bufferoffset = 0;
8349         rsurface.modelgeneratedvertex = true;
8350         rsurface.modellightmapcolor4f  = (float *)color4f;
8351         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8352         rsurface.modellightmapcolor4f_bufferoffset = 0;
8353         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8354         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8355         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8356         rsurface.modeltexcoordlightmap2f  = NULL;
8357         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8358         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8359         rsurface.modelelement3i = (int *)element3i;
8360         rsurface.modelelement3i_indexbuffer = NULL;
8361         rsurface.modelelement3i_bufferoffset = 0;
8362         rsurface.modelelement3s = (unsigned short *)element3s;
8363         rsurface.modelelement3s_indexbuffer = NULL;
8364         rsurface.modelelement3s_bufferoffset = 0;
8365         rsurface.modellightmapoffsets = NULL;
8366         rsurface.modelsurfaces = NULL;
8367         rsurface.batchgeneratedvertex = false;
8368         rsurface.batchfirstvertex = 0;
8369         rsurface.batchnumvertices = 0;
8370         rsurface.batchfirsttriangle = 0;
8371         rsurface.batchnumtriangles = 0;
8372         rsurface.batchvertex3f  = NULL;
8373         rsurface.batchvertex3f_vertexbuffer = NULL;
8374         rsurface.batchvertex3f_bufferoffset = 0;
8375         rsurface.batchsvector3f = NULL;
8376         rsurface.batchsvector3f_vertexbuffer = NULL;
8377         rsurface.batchsvector3f_bufferoffset = 0;
8378         rsurface.batchtvector3f = NULL;
8379         rsurface.batchtvector3f_vertexbuffer = NULL;
8380         rsurface.batchtvector3f_bufferoffset = 0;
8381         rsurface.batchnormal3f  = NULL;
8382         rsurface.batchnormal3f_vertexbuffer = NULL;
8383         rsurface.batchnormal3f_bufferoffset = 0;
8384         rsurface.batchlightmapcolor4f = NULL;
8385         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8386         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8387         rsurface.batchtexcoordtexture2f = NULL;
8388         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8389         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8390         rsurface.batchtexcoordlightmap2f = NULL;
8391         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8392         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8393         rsurface.batchvertexmesh = NULL;
8394         rsurface.batchvertexmeshbuffer = NULL;
8395         rsurface.batchvertex3fbuffer = NULL;
8396         rsurface.batchelement3i = NULL;
8397         rsurface.batchelement3i_indexbuffer = NULL;
8398         rsurface.batchelement3i_bufferoffset = 0;
8399         rsurface.batchelement3s = NULL;
8400         rsurface.batchelement3s_indexbuffer = NULL;
8401         rsurface.batchelement3s_bufferoffset = 0;
8402         rsurface.passcolor4f = NULL;
8403         rsurface.passcolor4f_vertexbuffer = NULL;
8404         rsurface.passcolor4f_bufferoffset = 0;
8405
8406         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8407         {
8408                 if ((wantnormals || wanttangents) && !normal3f)
8409                 {
8410                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8411                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8412                 }
8413                 if (wanttangents && !svector3f)
8414                 {
8415                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8416                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8417                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8418                 }
8419         }
8420 }
8421
8422 float RSurf_FogPoint(const float *v)
8423 {
8424         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8425         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8426         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8427         float FogHeightFade = r_refdef.fogheightfade;
8428         float fogfrac;
8429         unsigned int fogmasktableindex;
8430         if (r_refdef.fogplaneviewabove)
8431                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8432         else
8433                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8434         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8435         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8436 }
8437
8438 float RSurf_FogVertex(const float *v)
8439 {
8440         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8441         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8442         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8443         float FogHeightFade = rsurface.fogheightfade;
8444         float fogfrac;
8445         unsigned int fogmasktableindex;
8446         if (r_refdef.fogplaneviewabove)
8447                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8448         else
8449                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8450         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8451         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8452 }
8453
8454 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8455 {
8456         int i;
8457         for (i = 0;i < numelements;i++)
8458                 outelement3i[i] = inelement3i[i] + adjust;
8459 }
8460
8461 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8462 extern cvar_t gl_vbo;
8463 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8464 {
8465         int deformindex;
8466         int firsttriangle;
8467         int numtriangles;
8468         int firstvertex;
8469         int endvertex;
8470         int numvertices;
8471         int surfacefirsttriangle;
8472         int surfacenumtriangles;
8473         int surfacefirstvertex;
8474         int surfaceendvertex;
8475         int surfacenumvertices;
8476         int batchnumvertices;
8477         int batchnumtriangles;
8478         int needsupdate;
8479         int i, j;
8480         qboolean gaps;
8481         qboolean dynamicvertex;
8482         float amplitude;
8483         float animpos;
8484         float scale;
8485         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8486         float waveparms[4];
8487         q3shaderinfo_deform_t *deform;
8488         const msurface_t *surface, *firstsurface;
8489         r_vertexmesh_t *vertexmesh;
8490         if (!texturenumsurfaces)
8491                 return;
8492         // find vertex range of this surface batch
8493         gaps = false;
8494         firstsurface = texturesurfacelist[0];
8495         firsttriangle = firstsurface->num_firsttriangle;
8496         batchnumvertices = 0;
8497         batchnumtriangles = 0;
8498         firstvertex = endvertex = firstsurface->num_firstvertex;
8499         for (i = 0;i < texturenumsurfaces;i++)
8500         {
8501                 surface = texturesurfacelist[i];
8502                 if (surface != firstsurface + i)
8503                         gaps = true;
8504                 surfacefirstvertex = surface->num_firstvertex;
8505                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8506                 surfacenumvertices = surface->num_vertices;
8507                 surfacenumtriangles = surface->num_triangles;
8508                 if (firstvertex > surfacefirstvertex)
8509                         firstvertex = surfacefirstvertex;
8510                 if (endvertex < surfaceendvertex)
8511                         endvertex = surfaceendvertex;
8512                 batchnumvertices += surfacenumvertices;
8513                 batchnumtriangles += surfacenumtriangles;
8514         }
8515
8516         // we now know the vertex range used, and if there are any gaps in it
8517         rsurface.batchfirstvertex = firstvertex;
8518         rsurface.batchnumvertices = endvertex - firstvertex;
8519         rsurface.batchfirsttriangle = firsttriangle;
8520         rsurface.batchnumtriangles = batchnumtriangles;
8521
8522         // this variable holds flags for which properties have been updated that
8523         // may require regenerating vertexmesh array...
8524         needsupdate = 0;
8525
8526         // check if any dynamic vertex processing must occur
8527         dynamicvertex = false;
8528
8529         // if there is a chance of animated vertex colors, it's a dynamic batch
8530         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8531         {
8532                 dynamicvertex = true;
8533                 batchneed |= BATCHNEED_NOGAPS;
8534                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8535         }
8536
8537         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8538         {
8539                 switch (deform->deform)
8540                 {
8541                 default:
8542                 case Q3DEFORM_PROJECTIONSHADOW:
8543                 case Q3DEFORM_TEXT0:
8544                 case Q3DEFORM_TEXT1:
8545                 case Q3DEFORM_TEXT2:
8546                 case Q3DEFORM_TEXT3:
8547                 case Q3DEFORM_TEXT4:
8548                 case Q3DEFORM_TEXT5:
8549                 case Q3DEFORM_TEXT6:
8550                 case Q3DEFORM_TEXT7:
8551                 case Q3DEFORM_NONE:
8552                         break;
8553                 case Q3DEFORM_AUTOSPRITE:
8554                         dynamicvertex = true;
8555                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8556                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8557                         break;
8558                 case Q3DEFORM_AUTOSPRITE2:
8559                         dynamicvertex = true;
8560                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8561                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8562                         break;
8563                 case Q3DEFORM_NORMAL:
8564                         dynamicvertex = true;
8565                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8566                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8567                         break;
8568                 case Q3DEFORM_WAVE:
8569                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8570                                 break; // if wavefunc is a nop, ignore this transform
8571                         dynamicvertex = true;
8572                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8573                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8574                         break;
8575                 case Q3DEFORM_BULGE:
8576                         dynamicvertex = true;
8577                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8579                         break;
8580                 case Q3DEFORM_MOVE:
8581                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8582                                 break; // if wavefunc is a nop, ignore this transform
8583                         dynamicvertex = true;
8584                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8585                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8586                         break;
8587                 }
8588         }
8589         switch(rsurface.texture->tcgen.tcgen)
8590         {
8591         default:
8592         case Q3TCGEN_TEXTURE:
8593                 break;
8594         case Q3TCGEN_LIGHTMAP:
8595                 dynamicvertex = true;
8596                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8597                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8598                 break;
8599         case Q3TCGEN_VECTOR:
8600                 dynamicvertex = true;
8601                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8602                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8603                 break;
8604         case Q3TCGEN_ENVIRONMENT:
8605                 dynamicvertex = true;
8606                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8607                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8608                 break;
8609         }
8610         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8611         {
8612                 dynamicvertex = true;
8613                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8614                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8615         }
8616
8617         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8618         {
8619                 dynamicvertex = true;
8620                 batchneed |= BATCHNEED_NOGAPS;
8621                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8622         }
8623
8624         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8625         {
8626                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8627                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8628                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8629                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8630                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8631                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8632                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8633         }
8634
8635         // when the model data has no vertex buffer (dynamic mesh), we need to
8636         // eliminate gaps
8637         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8638                 batchneed |= BATCHNEED_NOGAPS;
8639
8640         // if needsupdate, we have to do a dynamic vertex batch for sure
8641         if (needsupdate & batchneed)
8642                 dynamicvertex = true;
8643
8644         // see if we need to build vertexmesh from arrays
8645         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8646                 dynamicvertex = true;
8647
8648         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8649         // also some drivers strongly dislike firstvertex
8650         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8651                 dynamicvertex = true;
8652
8653         rsurface.batchvertex3f = rsurface.modelvertex3f;
8654         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8655         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8656         rsurface.batchsvector3f = rsurface.modelsvector3f;
8657         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8658         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8659         rsurface.batchtvector3f = rsurface.modeltvector3f;
8660         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8661         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8662         rsurface.batchnormal3f = rsurface.modelnormal3f;
8663         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8664         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8665         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8666         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8667         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8668         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8669         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8670         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8671         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8672         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8673         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8674         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8675         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8676         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8677         rsurface.batchelement3i = rsurface.modelelement3i;
8678         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8679         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8680         rsurface.batchelement3s = rsurface.modelelement3s;
8681         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8682         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8683
8684         // if any dynamic vertex processing has to occur in software, we copy the
8685         // entire surface list together before processing to rebase the vertices
8686         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8687         //
8688         // if any gaps exist and we do not have a static vertex buffer, we have to
8689         // copy the surface list together to avoid wasting upload bandwidth on the
8690         // vertices in the gaps.
8691         //
8692         // if gaps exist and we have a static vertex buffer, we still have to
8693         // combine the index buffer ranges into one dynamic index buffer.
8694         //
8695         // in all cases we end up with data that can be drawn in one call.
8696
8697         if (!dynamicvertex)
8698         {
8699                 // static vertex data, just set pointers...
8700                 rsurface.batchgeneratedvertex = false;
8701                 // if there are gaps, we want to build a combined index buffer,
8702                 // otherwise use the original static buffer with an appropriate offset
8703                 if (gaps)
8704                 {
8705                         // build a new triangle elements array for this batch
8706                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8707                         rsurface.batchfirsttriangle = 0;
8708                         numtriangles = 0;
8709                         for (i = 0;i < texturenumsurfaces;i++)
8710                         {
8711                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8712                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8713                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8714                                 numtriangles += surfacenumtriangles;
8715                         }
8716                         rsurface.batchelement3i_indexbuffer = NULL;
8717                         rsurface.batchelement3i_bufferoffset = 0;
8718                         rsurface.batchelement3s = NULL;
8719                         rsurface.batchelement3s_indexbuffer = NULL;
8720                         rsurface.batchelement3s_bufferoffset = 0;
8721                         if (endvertex <= 65536)
8722                         {
8723                                 // make a 16bit (unsigned short) index array if possible
8724                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8725                                 for (i = 0;i < numtriangles*3;i++)
8726                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8727                         }
8728                 }
8729                 return;
8730         }
8731
8732         // something needs software processing, do it for real...
8733         // we only directly handle separate array data in this case and then
8734         // generate interleaved data if needed...
8735         rsurface.batchgeneratedvertex = true;
8736
8737         // now copy the vertex data into a combined array and make an index array
8738         // (this is what Quake3 does all the time)
8739         //if (gaps || rsurface.batchfirstvertex)
8740         {
8741                 rsurface.batchvertex3fbuffer = NULL;
8742                 rsurface.batchvertexmesh = NULL;
8743                 rsurface.batchvertexmeshbuffer = NULL;
8744                 rsurface.batchvertex3f = NULL;
8745                 rsurface.batchvertex3f_vertexbuffer = NULL;
8746                 rsurface.batchvertex3f_bufferoffset = 0;
8747                 rsurface.batchsvector3f = NULL;
8748                 rsurface.batchsvector3f_vertexbuffer = NULL;
8749                 rsurface.batchsvector3f_bufferoffset = 0;
8750                 rsurface.batchtvector3f = NULL;
8751                 rsurface.batchtvector3f_vertexbuffer = NULL;
8752                 rsurface.batchtvector3f_bufferoffset = 0;
8753                 rsurface.batchnormal3f = NULL;
8754                 rsurface.batchnormal3f_vertexbuffer = NULL;
8755                 rsurface.batchnormal3f_bufferoffset = 0;
8756                 rsurface.batchlightmapcolor4f = NULL;
8757                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8758                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8759                 rsurface.batchtexcoordtexture2f = NULL;
8760                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8761                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8762                 rsurface.batchtexcoordlightmap2f = NULL;
8763                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8764                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8765                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8766                 rsurface.batchelement3i_indexbuffer = NULL;
8767                 rsurface.batchelement3i_bufferoffset = 0;
8768                 rsurface.batchelement3s = NULL;
8769                 rsurface.batchelement3s_indexbuffer = NULL;
8770                 rsurface.batchelement3s_bufferoffset = 0;
8771                 // we'll only be setting up certain arrays as needed
8772                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8773                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8774                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8775                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8776                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8777                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8778                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8779                 {
8780                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8781                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8782                 }
8783                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8784                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8785                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8786                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8787                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8788                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8789                 numvertices = 0;
8790                 numtriangles = 0;
8791                 for (i = 0;i < texturenumsurfaces;i++)
8792                 {
8793                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8794                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8795                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8796                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8797                         // copy only the data requested
8798                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8799                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8800                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8801                         {
8802                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8803                                 {
8804                                         if (rsurface.batchvertex3f)
8805                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8806                                         else
8807                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8808                                 }
8809                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8810                                 {
8811                                         if (rsurface.modelnormal3f)
8812                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8813                                         else
8814                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8815                                 }
8816                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8817                                 {
8818                                         if (rsurface.modelsvector3f)
8819                                         {
8820                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8821                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8822                                         }
8823                                         else
8824                                         {
8825                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8826                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8827                                         }
8828                                 }
8829                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8830                                 {
8831                                         if (rsurface.modellightmapcolor4f)
8832                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8833                                         else
8834                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8835                                 }
8836                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8837                                 {
8838                                         if (rsurface.modeltexcoordtexture2f)
8839                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8840                                         else
8841                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8842                                 }
8843                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8844                                 {
8845                                         if (rsurface.modeltexcoordlightmap2f)
8846                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8847                                         else
8848                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8849                                 }
8850                         }
8851                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8852                         numvertices += surfacenumvertices;
8853                         numtriangles += surfacenumtriangles;
8854                 }
8855
8856                 // generate a 16bit index array as well if possible
8857                 // (in general, dynamic batches fit)
8858                 if (numvertices <= 65536)
8859                 {
8860                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8861                         for (i = 0;i < numtriangles*3;i++)
8862                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8863                 }
8864
8865                 // since we've copied everything, the batch now starts at 0
8866                 rsurface.batchfirstvertex = 0;
8867                 rsurface.batchnumvertices = batchnumvertices;
8868                 rsurface.batchfirsttriangle = 0;
8869                 rsurface.batchnumtriangles = batchnumtriangles;
8870         }
8871
8872         // q1bsp surfaces rendered in vertex color mode have to have colors
8873         // calculated based on lightstyles
8874         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8875         {
8876                 // generate color arrays for the surfaces in this list
8877                 int c[4];
8878                 int scale;
8879                 int size3;
8880                 const int *offsets;
8881                 const unsigned char *lm;
8882                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8883                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8884                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8885                 numvertices = 0;
8886                 for (i = 0;i < texturenumsurfaces;i++)
8887                 {
8888                         surface = texturesurfacelist[i];
8889                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8890                         surfacenumvertices = surface->num_vertices;
8891                         if (surface->lightmapinfo->samples)
8892                         {
8893                                 for (j = 0;j < surfacenumvertices;j++)
8894                                 {
8895                                         lm = surface->lightmapinfo->samples + offsets[j];
8896                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8897                                         VectorScale(lm, scale, c);
8898                                         if (surface->lightmapinfo->styles[1] != 255)
8899                                         {
8900                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8901                                                 lm += size3;
8902                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8903                                                 VectorMA(c, scale, lm, c);
8904                                                 if (surface->lightmapinfo->styles[2] != 255)
8905                                                 {
8906                                                         lm += size3;
8907                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8908                                                         VectorMA(c, scale, lm, c);
8909                                                         if (surface->lightmapinfo->styles[3] != 255)
8910                                                         {
8911                                                                 lm += size3;
8912                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8913                                                                 VectorMA(c, scale, lm, c);
8914                                                         }
8915                                                 }
8916                                         }
8917                                         c[0] >>= 7;
8918                                         c[1] >>= 7;
8919                                         c[2] >>= 7;
8920                                         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);
8921                                         numvertices++;
8922                                 }
8923                         }
8924                         else
8925                         {
8926                                 for (j = 0;j < surfacenumvertices;j++)
8927                                 {
8928                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8929                                         numvertices++;
8930                                 }
8931                         }
8932                 }
8933         }
8934
8935         // if vertices are deformed (sprite flares and things in maps, possibly
8936         // water waves, bulges and other deformations), modify the copied vertices
8937         // in place
8938         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8939         {
8940                 switch (deform->deform)
8941                 {
8942                 default:
8943                 case Q3DEFORM_PROJECTIONSHADOW:
8944                 case Q3DEFORM_TEXT0:
8945                 case Q3DEFORM_TEXT1:
8946                 case Q3DEFORM_TEXT2:
8947                 case Q3DEFORM_TEXT3:
8948                 case Q3DEFORM_TEXT4:
8949                 case Q3DEFORM_TEXT5:
8950                 case Q3DEFORM_TEXT6:
8951                 case Q3DEFORM_TEXT7:
8952                 case Q3DEFORM_NONE:
8953                         break;
8954                 case Q3DEFORM_AUTOSPRITE:
8955                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8956                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8957                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8958                         VectorNormalize(newforward);
8959                         VectorNormalize(newright);
8960                         VectorNormalize(newup);
8961 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8962 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8963 //                      rsurface.batchvertex3f_bufferoffset = 0;
8964 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8965 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8966 //                      rsurface.batchsvector3f_bufferoffset = 0;
8967 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8968 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8969 //                      rsurface.batchtvector3f_bufferoffset = 0;
8970 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8971 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8972 //                      rsurface.batchnormal3f_bufferoffset = 0;
8973                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8974                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8975                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8976                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8977                                 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);
8978                         // a single autosprite surface can contain multiple sprites...
8979                         for (j = 0;j < batchnumvertices - 3;j += 4)
8980                         {
8981                                 VectorClear(center);
8982                                 for (i = 0;i < 4;i++)
8983                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8984                                 VectorScale(center, 0.25f, center);
8985                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8986                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8987                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8988                                 for (i = 0;i < 4;i++)
8989                                 {
8990                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8991                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8992                                 }
8993                         }
8994                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8995                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8996                         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);
8997                         break;
8998                 case Q3DEFORM_AUTOSPRITE2:
8999                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9000                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9001                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9002                         VectorNormalize(newforward);
9003                         VectorNormalize(newright);
9004                         VectorNormalize(newup);
9005 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9006 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9007 //                      rsurface.batchvertex3f_bufferoffset = 0;
9008                         {
9009                                 const float *v1, *v2;
9010                                 vec3_t start, end;
9011                                 float f, l;
9012                                 struct
9013                                 {
9014                                         float length2;
9015                                         const float *v1;
9016                                         const float *v2;
9017                                 }
9018                                 shortest[2];
9019                                 memset(shortest, 0, sizeof(shortest));
9020                                 // a single autosprite surface can contain multiple sprites...
9021                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9022                                 {
9023                                         VectorClear(center);
9024                                         for (i = 0;i < 4;i++)
9025                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9026                                         VectorScale(center, 0.25f, center);
9027                                         // find the two shortest edges, then use them to define the
9028                                         // axis vectors for rotating around the central axis
9029                                         for (i = 0;i < 6;i++)
9030                                         {
9031                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9032                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9033                                                 l = VectorDistance2(v1, v2);
9034                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9035                                                 if (v1[2] != v2[2])
9036                                                         l += (1.0f / 1024.0f);
9037                                                 if (shortest[0].length2 > l || i == 0)
9038                                                 {
9039                                                         shortest[1] = shortest[0];
9040                                                         shortest[0].length2 = l;
9041                                                         shortest[0].v1 = v1;
9042                                                         shortest[0].v2 = v2;
9043                                                 }
9044                                                 else if (shortest[1].length2 > l || i == 1)
9045                                                 {
9046                                                         shortest[1].length2 = l;
9047                                                         shortest[1].v1 = v1;
9048                                                         shortest[1].v2 = v2;
9049                                                 }
9050                                         }
9051                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9052                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9053                                         // this calculates the right vector from the shortest edge
9054                                         // and the up vector from the edge midpoints
9055                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9056                                         VectorNormalize(right);
9057                                         VectorSubtract(end, start, up);
9058                                         VectorNormalize(up);
9059                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9060                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9061                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9062                                         VectorNegate(forward, forward);
9063                                         VectorReflect(forward, 0, up, forward);
9064                                         VectorNormalize(forward);
9065                                         CrossProduct(up, forward, newright);
9066                                         VectorNormalize(newright);
9067                                         // rotate the quad around the up axis vector, this is made
9068                                         // especially easy by the fact we know the quad is flat,
9069                                         // so we only have to subtract the center position and
9070                                         // measure distance along the right vector, and then
9071                                         // multiply that by the newright vector and add back the
9072                                         // center position
9073                                         // we also need to subtract the old position to undo the
9074                                         // displacement from the center, which we do with a
9075                                         // DotProduct, the subtraction/addition of center is also
9076                                         // optimized into DotProducts here
9077                                         l = DotProduct(right, center);
9078                                         for (i = 0;i < 4;i++)
9079                                         {
9080                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9081                                                 f = DotProduct(right, v1) - l;
9082                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9083                                         }
9084                                 }
9085                         }
9086                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9087                         {
9088 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9090 //                              rsurface.batchnormal3f_bufferoffset = 0;
9091                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9092                         }
9093                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9094                         {
9095 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9096 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9097 //                              rsurface.batchsvector3f_bufferoffset = 0;
9098 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9099 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9100 //                              rsurface.batchtvector3f_bufferoffset = 0;
9101                                 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);
9102                         }
9103                         break;
9104                 case Q3DEFORM_NORMAL:
9105                         // deform the normals to make reflections wavey
9106                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9107                         rsurface.batchnormal3f_vertexbuffer = NULL;
9108                         rsurface.batchnormal3f_bufferoffset = 0;
9109                         for (j = 0;j < batchnumvertices;j++)
9110                         {
9111                                 float vertex[3];
9112                                 float *normal = rsurface.batchnormal3f + 3*j;
9113                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9114                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9115                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9116                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9117                                 VectorNormalize(normal);
9118                         }
9119                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9120                         {
9121 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9122 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9123 //                              rsurface.batchsvector3f_bufferoffset = 0;
9124 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9125 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9126 //                              rsurface.batchtvector3f_bufferoffset = 0;
9127                                 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);
9128                         }
9129                         break;
9130                 case Q3DEFORM_WAVE:
9131                         // deform vertex array to make wavey water and flags and such
9132                         waveparms[0] = deform->waveparms[0];
9133                         waveparms[1] = deform->waveparms[1];
9134                         waveparms[2] = deform->waveparms[2];
9135                         waveparms[3] = deform->waveparms[3];
9136                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9137                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9138                         // this is how a divisor of vertex influence on deformation
9139                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9140                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9141 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9142 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9143 //                      rsurface.batchvertex3f_bufferoffset = 0;
9144 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9145 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9146 //                      rsurface.batchnormal3f_bufferoffset = 0;
9147                         for (j = 0;j < batchnumvertices;j++)
9148                         {
9149                                 // if the wavefunc depends on time, evaluate it per-vertex
9150                                 if (waveparms[3])
9151                                 {
9152                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9153                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9154                                 }
9155                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9156                         }
9157                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9158                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9159                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9160                         {
9161 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9162 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9163 //                              rsurface.batchsvector3f_bufferoffset = 0;
9164 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9165 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9166 //                              rsurface.batchtvector3f_bufferoffset = 0;
9167                                 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);
9168                         }
9169                         break;
9170                 case Q3DEFORM_BULGE:
9171                         // deform vertex array to make the surface have moving bulges
9172 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9173 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9174 //                      rsurface.batchvertex3f_bufferoffset = 0;
9175 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9176 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9177 //                      rsurface.batchnormal3f_bufferoffset = 0;
9178                         for (j = 0;j < batchnumvertices;j++)
9179                         {
9180                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9181                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9182                         }
9183                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9184                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9185                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9186                         {
9187 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9188 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9189 //                              rsurface.batchsvector3f_bufferoffset = 0;
9190 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchtvector3f_bufferoffset = 0;
9193                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9194                         }
9195                         break;
9196                 case Q3DEFORM_MOVE:
9197                         // deform vertex array
9198                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9199                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9200                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9201                         VectorScale(deform->parms, scale, waveparms);
9202 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9203 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9204 //                      rsurface.batchvertex3f_bufferoffset = 0;
9205                         for (j = 0;j < batchnumvertices;j++)
9206                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9207                         break;
9208                 }
9209         }
9210
9211         // generate texcoords based on the chosen texcoord source
9212         switch(rsurface.texture->tcgen.tcgen)
9213         {
9214         default:
9215         case Q3TCGEN_TEXTURE:
9216                 break;
9217         case Q3TCGEN_LIGHTMAP:
9218 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9219 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9220 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9221                 if (rsurface.batchtexcoordlightmap2f)
9222                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9223                 break;
9224         case Q3TCGEN_VECTOR:
9225 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9226 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9227 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9228                 for (j = 0;j < batchnumvertices;j++)
9229                 {
9230                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9231                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9232                 }
9233                 break;
9234         case Q3TCGEN_ENVIRONMENT:
9235                 // make environment reflections using a spheremap
9236                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9237                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9238                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9239                 for (j = 0;j < batchnumvertices;j++)
9240                 {
9241                         // identical to Q3A's method, but executed in worldspace so
9242                         // carried models can be shiny too
9243
9244                         float viewer[3], d, reflected[3], worldreflected[3];
9245
9246                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9247                         // VectorNormalize(viewer);
9248
9249                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9250
9251                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9252                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9253                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9254                         // note: this is proportinal to viewer, so we can normalize later
9255
9256                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9257                         VectorNormalize(worldreflected);
9258
9259                         // note: this sphere map only uses world x and z!
9260                         // so positive and negative y will LOOK THE SAME.
9261                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9262                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9263                 }
9264                 break;
9265         }
9266         // the only tcmod that needs software vertex processing is turbulent, so
9267         // check for it here and apply the changes if needed
9268         // and we only support that as the first one
9269         // (handling a mixture of turbulent and other tcmods would be problematic
9270         //  without punting it entirely to a software path)
9271         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9272         {
9273                 amplitude = rsurface.texture->tcmods[0].parms[1];
9274                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9275 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9276 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9277 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9278                 for (j = 0;j < batchnumvertices;j++)
9279                 {
9280                         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);
9281                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9282                 }
9283         }
9284
9285         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9286         {
9287                 // convert the modified arrays to vertex structs
9288 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9289 //              rsurface.batchvertexmeshbuffer = NULL;
9290                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9291                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9292                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9293                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9294                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9295                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9296                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9297                 {
9298                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9299                         {
9300                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9301                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9302                         }
9303                 }
9304                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9305                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9306                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9307                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9308                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9309                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9310                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9311                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9312                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9313         }
9314 }
9315
9316 void RSurf_DrawBatch(void)
9317 {
9318         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9319         // through the pipeline, killing it earlier in the pipeline would have
9320         // per-surface overhead rather than per-batch overhead, so it's best to
9321         // reject it here, before it hits glDraw.
9322         if (rsurface.batchnumtriangles == 0)
9323                 return;
9324 #if 0
9325         // batch debugging code
9326         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9327         {
9328                 int i;
9329                 int j;
9330                 int c;
9331                 const int *e;
9332                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9333                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9334                 {
9335                         c = e[i];
9336                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9337                         {
9338                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9339                                 {
9340                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9341                                                 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);
9342                                         break;
9343                                 }
9344                         }
9345                 }
9346         }
9347 #endif
9348         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);
9349 }
9350
9351 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9352 {
9353         // pick the closest matching water plane
9354         int planeindex, vertexindex, bestplaneindex = -1;
9355         float d, bestd;
9356         vec3_t vert;
9357         const float *v;
9358         r_waterstate_waterplane_t *p;
9359         qboolean prepared = false;
9360         bestd = 0;
9361         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9362         {
9363                 if(p->camera_entity != rsurface.texture->camera_entity)
9364                         continue;
9365                 d = 0;
9366                 if(!prepared)
9367                 {
9368                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9369                         prepared = true;
9370                         if(rsurface.batchnumvertices == 0)
9371                                 break;
9372                 }
9373                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9374                 {
9375                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9376                         d += fabs(PlaneDiff(vert, &p->plane));
9377                 }
9378                 if (bestd > d || bestplaneindex < 0)
9379                 {
9380                         bestd = d;
9381                         bestplaneindex = planeindex;
9382                 }
9383         }
9384         return bestplaneindex;
9385         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9386         // this situation though, as it might be better to render single larger
9387         // batches with useless stuff (backface culled for example) than to
9388         // render multiple smaller batches
9389 }
9390
9391 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9392 {
9393         int i;
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;i < rsurface.batchnumvertices;i++)
9398                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9399 }
9400
9401 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9402 {
9403         int i;
9404         float f;
9405         const float *v;
9406         const float *c;
9407         float *c2;
9408         if (rsurface.passcolor4f)
9409         {
9410                 // generate color arrays
9411                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9412                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9413                 rsurface.passcolor4f_vertexbuffer = 0;
9414                 rsurface.passcolor4f_bufferoffset = 0;
9415                 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)
9416                 {
9417                         f = RSurf_FogVertex(v);
9418                         c2[0] = c[0] * f;
9419                         c2[1] = c[1] * f;
9420                         c2[2] = c[2] * f;
9421                         c2[3] = c[3];
9422                 }
9423         }
9424         else
9425         {
9426                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9427                 rsurface.passcolor4f_vertexbuffer = 0;
9428                 rsurface.passcolor4f_bufferoffset = 0;
9429                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9430                 {
9431                         f = RSurf_FogVertex(v);
9432                         c2[0] = f;
9433                         c2[1] = f;
9434                         c2[2] = f;
9435                         c2[3] = 1;
9436                 }
9437         }
9438 }
9439
9440 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9441 {
9442         int i;
9443         float f;
9444         const float *v;
9445         const float *c;
9446         float *c2;
9447         if (!rsurface.passcolor4f)
9448                 return;
9449         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9450         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9451         rsurface.passcolor4f_vertexbuffer = 0;
9452         rsurface.passcolor4f_bufferoffset = 0;
9453         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)
9454         {
9455                 f = RSurf_FogVertex(v);
9456                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9457                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9458                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9459                 c2[3] = c[3];
9460         }
9461 }
9462
9463 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9464 {
9465         int i;
9466         const float *c;
9467         float *c2;
9468         if (!rsurface.passcolor4f)
9469                 return;
9470         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9471         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9472         rsurface.passcolor4f_vertexbuffer = 0;
9473         rsurface.passcolor4f_bufferoffset = 0;
9474         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9475         {
9476                 c2[0] = c[0] * r;
9477                 c2[1] = c[1] * g;
9478                 c2[2] = c[2] * b;
9479                 c2[3] = c[3] * a;
9480         }
9481 }
9482
9483 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9484 {
9485         int i;
9486         const float *c;
9487         float *c2;
9488         if (!rsurface.passcolor4f)
9489                 return;
9490         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9491         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9492         rsurface.passcolor4f_vertexbuffer = 0;
9493         rsurface.passcolor4f_bufferoffset = 0;
9494         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9495         {
9496                 c2[0] = c[0] + r_refdef.scene.ambient;
9497                 c2[1] = c[1] + r_refdef.scene.ambient;
9498                 c2[2] = c[2] + r_refdef.scene.ambient;
9499                 c2[3] = c[3];
9500         }
9501 }
9502
9503 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9504 {
9505         // TODO: optimize
9506         rsurface.passcolor4f = NULL;
9507         rsurface.passcolor4f_vertexbuffer = 0;
9508         rsurface.passcolor4f_bufferoffset = 0;
9509         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9510         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9511         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9512         GL_Color(r, g, b, a);
9513         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9514         RSurf_DrawBatch();
9515 }
9516
9517 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9518 {
9519         // TODO: optimize applyfog && applycolor case
9520         // just apply fog if necessary, and tint the fog color array if necessary
9521         rsurface.passcolor4f = NULL;
9522         rsurface.passcolor4f_vertexbuffer = 0;
9523         rsurface.passcolor4f_bufferoffset = 0;
9524         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9525         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9526         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9527         GL_Color(r, g, b, a);
9528         RSurf_DrawBatch();
9529 }
9530
9531 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9532 {
9533         // TODO: optimize
9534         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9535         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9536         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9537         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9538         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9539         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9540         GL_Color(r, g, b, a);
9541         RSurf_DrawBatch();
9542 }
9543
9544 static void RSurf_DrawBatch_GL11_ClampColor(void)
9545 {
9546         int i;
9547         const float *c1;
9548         float *c2;
9549         if (!rsurface.passcolor4f)
9550                 return;
9551         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9552         {
9553                 c2[0] = bound(0.0f, c1[0], 1.0f);
9554                 c2[1] = bound(0.0f, c1[1], 1.0f);
9555                 c2[2] = bound(0.0f, c1[2], 1.0f);
9556                 c2[3] = bound(0.0f, c1[3], 1.0f);
9557         }
9558 }
9559
9560 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9561 {
9562         int i;
9563         float f;
9564         const float *v;
9565         const float *n;
9566         float *c;
9567         //vec3_t eyedir;
9568
9569         // fake shading
9570         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9571         rsurface.passcolor4f_vertexbuffer = 0;
9572         rsurface.passcolor4f_bufferoffset = 0;
9573         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)
9574         {
9575                 f = -DotProduct(r_refdef.view.forward, n);
9576                 f = max(0, f);
9577                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9578                 f *= r_refdef.lightmapintensity;
9579                 Vector4Set(c, f, f, f, 1);
9580         }
9581 }
9582
9583 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9584 {
9585         RSurf_DrawBatch_GL11_ApplyFakeLight();
9586         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9587         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9588         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9589         GL_Color(r, g, b, a);
9590         RSurf_DrawBatch();
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9594 {
9595         int i;
9596         float f;
9597         float alpha;
9598         const float *v;
9599         const float *n;
9600         float *c;
9601         vec3_t ambientcolor;
9602         vec3_t diffusecolor;
9603         vec3_t lightdir;
9604         // TODO: optimize
9605         // model lighting
9606         VectorCopy(rsurface.modellight_lightdir, lightdir);
9607         f = 0.5f * r_refdef.lightmapintensity;
9608         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9609         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9610         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9611         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9612         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9613         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9614         alpha = *a;
9615         if (VectorLength2(diffusecolor) > 0)
9616         {
9617                 // q3-style directional shading
9618                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9619                 rsurface.passcolor4f_vertexbuffer = 0;
9620                 rsurface.passcolor4f_bufferoffset = 0;
9621                 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)
9622                 {
9623                         if ((f = DotProduct(n, lightdir)) > 0)
9624                                 VectorMA(ambientcolor, f, diffusecolor, c);
9625                         else
9626                                 VectorCopy(ambientcolor, c);
9627                         c[3] = alpha;
9628                 }
9629                 *r = 1;
9630                 *g = 1;
9631                 *b = 1;
9632                 *a = 1;
9633                 *applycolor = false;
9634         }
9635         else
9636         {
9637                 *r = ambientcolor[0];
9638                 *g = ambientcolor[1];
9639                 *b = ambientcolor[2];
9640                 rsurface.passcolor4f = NULL;
9641                 rsurface.passcolor4f_vertexbuffer = 0;
9642                 rsurface.passcolor4f_bufferoffset = 0;
9643         }
9644 }
9645
9646 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9647 {
9648         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9649         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9650         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9651         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9652         GL_Color(r, g, b, a);
9653         RSurf_DrawBatch();
9654 }
9655
9656 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9657 {
9658         int i;
9659         float f;
9660         const float *v;
9661         float *c;
9662
9663         // fake shading
9664         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9665         rsurface.passcolor4f_vertexbuffer = 0;
9666         rsurface.passcolor4f_bufferoffset = 0;
9667
9668         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9669         {
9670                 f = 1 - RSurf_FogVertex(v);
9671                 c[0] = r;
9672                 c[1] = g;
9673                 c[2] = b;
9674                 c[3] = f * a;
9675         }
9676 }
9677
9678 void RSurf_SetupDepthAndCulling(void)
9679 {
9680         // submodels are biased to avoid z-fighting with world surfaces that they
9681         // may be exactly overlapping (avoids z-fighting artifacts on certain
9682         // doors and things in Quake maps)
9683         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9684         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9685         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9686         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9687 }
9688
9689 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9690 {
9691         // transparent sky would be ridiculous
9692         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9693                 return;
9694         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9695         skyrenderlater = true;
9696         RSurf_SetupDepthAndCulling();
9697         GL_DepthMask(true);
9698         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9699         // skymasking on them, and Quake3 never did sky masking (unlike
9700         // software Quake and software Quake2), so disable the sky masking
9701         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9702         // and skymasking also looks very bad when noclipping outside the
9703         // level, so don't use it then either.
9704         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9705         {
9706                 R_Mesh_ResetTextureState();
9707                 if (skyrendermasked)
9708                 {
9709                         R_SetupShader_DepthOrShadow(false);
9710                         // depth-only (masking)
9711                         GL_ColorMask(0,0,0,0);
9712                         // just to make sure that braindead drivers don't draw
9713                         // anything despite that colormask...
9714                         GL_BlendFunc(GL_ZERO, GL_ONE);
9715                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9716                         if (rsurface.batchvertex3fbuffer)
9717                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9718                         else
9719                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9720                 }
9721                 else
9722                 {
9723                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9724                         // fog sky
9725                         GL_BlendFunc(GL_ONE, GL_ZERO);
9726                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9727                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9728                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9729                 }
9730                 RSurf_DrawBatch();
9731                 if (skyrendermasked)
9732                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9733         }
9734         R_Mesh_ResetTextureState();
9735         GL_Color(1, 1, 1, 1);
9736 }
9737
9738 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9739 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9740 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9741 {
9742         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9743                 return;
9744         if (prepass)
9745         {
9746                 // render screenspace normalmap to texture
9747                 GL_DepthMask(true);
9748                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9749                 RSurf_DrawBatch();
9750         }
9751
9752         // bind lightmap texture
9753
9754         // water/refraction/reflection/camera surfaces have to be handled specially
9755         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9756         {
9757                 int start, end, startplaneindex;
9758                 for (start = 0;start < texturenumsurfaces;start = end)
9759                 {
9760                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9761                         if(startplaneindex < 0)
9762                         {
9763                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9764                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9765                                 end = start + 1;
9766                                 continue;
9767                         }
9768                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9769                                 ;
9770                         // now that we have a batch using the same planeindex, render it
9771                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9772                         {
9773                                 // render water or distortion background
9774                                 GL_DepthMask(true);
9775                                 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);
9776                                 RSurf_DrawBatch();
9777                                 // blend surface on top
9778                                 GL_DepthMask(false);
9779                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9780                                 RSurf_DrawBatch();
9781                         }
9782                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9783                         {
9784                                 // render surface with reflection texture as input
9785                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9786                                 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);
9787                                 RSurf_DrawBatch();
9788                         }
9789                 }
9790                 return;
9791         }
9792
9793         // render surface batch normally
9794         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9795         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);
9796         RSurf_DrawBatch();
9797 }
9798
9799 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9800 {
9801         // OpenGL 1.3 path - anything not completely ancient
9802         qboolean applycolor;
9803         qboolean applyfog;
9804         int layerindex;
9805         const texturelayer_t *layer;
9806         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);
9807         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9808
9809         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9810         {
9811                 vec4_t layercolor;
9812                 int layertexrgbscale;
9813                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9814                 {
9815                         if (layerindex == 0)
9816                                 GL_AlphaTest(true);
9817                         else
9818                         {
9819                                 GL_AlphaTest(false);
9820                                 GL_DepthFunc(GL_EQUAL);
9821                         }
9822                 }
9823                 GL_DepthMask(layer->depthmask && writedepth);
9824                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9825                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9826                 {
9827                         layertexrgbscale = 4;
9828                         VectorScale(layer->color, 0.25f, layercolor);
9829                 }
9830                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9831                 {
9832                         layertexrgbscale = 2;
9833                         VectorScale(layer->color, 0.5f, layercolor);
9834                 }
9835                 else
9836                 {
9837                         layertexrgbscale = 1;
9838                         VectorScale(layer->color, 1.0f, layercolor);
9839                 }
9840                 layercolor[3] = layer->color[3];
9841                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9842                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9843                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9844                 switch (layer->type)
9845                 {
9846                 case TEXTURELAYERTYPE_LITTEXTURE:
9847                         // single-pass lightmapped texture with 2x rgbscale
9848                         R_Mesh_TexBind(0, r_texture_white);
9849                         R_Mesh_TexMatrix(0, NULL);
9850                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9851                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9852                         R_Mesh_TexBind(1, layer->texture);
9853                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9854                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9855                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9856                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9857                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9858                         else if (FAKELIGHT_ENABLED)
9859                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9860                         else if (rsurface.uselightmaptexture)
9861                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9862                         else
9863                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9864                         break;
9865                 case TEXTURELAYERTYPE_TEXTURE:
9866                         // singletexture unlit texture with transparency support
9867                         R_Mesh_TexBind(0, layer->texture);
9868                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9869                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9870                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9871                         R_Mesh_TexBind(1, 0);
9872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9873                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9874                         break;
9875                 case TEXTURELAYERTYPE_FOG:
9876                         // singletexture fogging
9877                         if (layer->texture)
9878                         {
9879                                 R_Mesh_TexBind(0, layer->texture);
9880                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9881                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9882                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9883                         }
9884                         else
9885                         {
9886                                 R_Mesh_TexBind(0, 0);
9887                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9888                         }
9889                         R_Mesh_TexBind(1, 0);
9890                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9891                         // generate a color array for the fog pass
9892                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9893                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9894                         RSurf_DrawBatch();
9895                         break;
9896                 default:
9897                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9898                 }
9899         }
9900         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9901         {
9902                 GL_DepthFunc(GL_LEQUAL);
9903                 GL_AlphaTest(false);
9904         }
9905 }
9906
9907 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9908 {
9909         // OpenGL 1.1 - crusty old voodoo path
9910         qboolean applyfog;
9911         int layerindex;
9912         const texturelayer_t *layer;
9913         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);
9914         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9915
9916         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9917         {
9918                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9919                 {
9920                         if (layerindex == 0)
9921                                 GL_AlphaTest(true);
9922                         else
9923                         {
9924                                 GL_AlphaTest(false);
9925                                 GL_DepthFunc(GL_EQUAL);
9926                         }
9927                 }
9928                 GL_DepthMask(layer->depthmask && writedepth);
9929                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9930                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9931                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9932                 switch (layer->type)
9933                 {
9934                 case TEXTURELAYERTYPE_LITTEXTURE:
9935                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9936                         {
9937                                 // two-pass lit texture with 2x rgbscale
9938                                 // first the lightmap pass
9939                                 R_Mesh_TexBind(0, r_texture_white);
9940                                 R_Mesh_TexMatrix(0, NULL);
9941                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9942                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9943                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9944                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9945                                 else if (FAKELIGHT_ENABLED)
9946                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9947                                 else if (rsurface.uselightmaptexture)
9948                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9949                                 else
9950                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9951                                 // then apply the texture to it
9952                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9953                                 R_Mesh_TexBind(0, layer->texture);
9954                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9955                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9956                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9957                                 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);
9958                         }
9959                         else
9960                         {
9961                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9962                                 R_Mesh_TexBind(0, layer->texture);
9963                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9964                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9965                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9966                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9967                                         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);
9968                                 else
9969                                         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);
9970                         }
9971                         break;
9972                 case TEXTURELAYERTYPE_TEXTURE:
9973                         // singletexture unlit texture with transparency support
9974                         R_Mesh_TexBind(0, layer->texture);
9975                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9976                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9977                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9978                         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);
9979                         break;
9980                 case TEXTURELAYERTYPE_FOG:
9981                         // singletexture fogging
9982                         if (layer->texture)
9983                         {
9984                                 R_Mesh_TexBind(0, layer->texture);
9985                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9986                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9987                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9988                         }
9989                         else
9990                         {
9991                                 R_Mesh_TexBind(0, 0);
9992                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9993                         }
9994                         // generate a color array for the fog pass
9995                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9996                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9997                         RSurf_DrawBatch();
9998                         break;
9999                 default:
10000                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10001                 }
10002         }
10003         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10004         {
10005                 GL_DepthFunc(GL_LEQUAL);
10006                 GL_AlphaTest(false);
10007         }
10008 }
10009
10010 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10011 {
10012         int vi;
10013         int j;
10014         r_vertexgeneric_t *batchvertex;
10015         float c[4];
10016
10017 //      R_Mesh_ResetTextureState();
10018         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10019
10020         if(rsurface.texture && rsurface.texture->currentskinframe)
10021         {
10022                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10023                 c[3] *= rsurface.texture->currentalpha;
10024         }
10025         else
10026         {
10027                 c[0] = 1;
10028                 c[1] = 0;
10029                 c[2] = 1;
10030                 c[3] = 1;
10031         }
10032
10033         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10034         {
10035                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10036                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10037                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10038         }
10039
10040         // brighten it up (as texture value 127 means "unlit")
10041         c[0] *= 2 * r_refdef.view.colorscale;
10042         c[1] *= 2 * r_refdef.view.colorscale;
10043         c[2] *= 2 * r_refdef.view.colorscale;
10044
10045         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10046                 c[3] *= r_wateralpha.value;
10047
10048         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10049         {
10050                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10051                 GL_DepthMask(false);
10052         }
10053         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10054         {
10055                 GL_BlendFunc(GL_ONE, GL_ONE);
10056                 GL_DepthMask(false);
10057         }
10058         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10059         {
10060                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10061                 GL_DepthMask(false);
10062         }
10063         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10064         {
10065                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10066                 GL_DepthMask(false);
10067         }
10068         else
10069         {
10070                 GL_BlendFunc(GL_ONE, GL_ZERO);
10071                 GL_DepthMask(writedepth);
10072         }
10073
10074         if (r_showsurfaces.integer == 3)
10075         {
10076                 rsurface.passcolor4f = NULL;
10077
10078                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10079                 {
10080                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10081
10082                         rsurface.passcolor4f = NULL;
10083                         rsurface.passcolor4f_vertexbuffer = 0;
10084                         rsurface.passcolor4f_bufferoffset = 0;
10085                 }
10086                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10087                 {
10088                         qboolean applycolor = true;
10089                         float one = 1.0;
10090
10091                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10092
10093                         r_refdef.lightmapintensity = 1;
10094                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10095                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10096                 }
10097                 else if (FAKELIGHT_ENABLED)
10098                 {
10099                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10100
10101                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10102                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10103                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10104                 }
10105                 else
10106                 {
10107                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10108
10109                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10110                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10111                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10112                 }
10113
10114                 if(!rsurface.passcolor4f)
10115                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10116
10117                 RSurf_DrawBatch_GL11_ApplyAmbient();
10118                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10119                 if(r_refdef.fogenabled)
10120                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10121                 RSurf_DrawBatch_GL11_ClampColor();
10122
10123                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10124                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10125                 RSurf_DrawBatch();
10126         }
10127         else if (!r_refdef.view.showdebug)
10128         {
10129                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10130                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10131                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10132                 {
10133                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10134                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10135                 }
10136                 R_Mesh_PrepareVertices_Generic_Unlock();
10137                 RSurf_DrawBatch();
10138         }
10139         else if (r_showsurfaces.integer == 4)
10140         {
10141                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10142                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10143                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10144                 {
10145                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10146                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10147                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10148                 }
10149                 R_Mesh_PrepareVertices_Generic_Unlock();
10150                 RSurf_DrawBatch();
10151         }
10152         else if (r_showsurfaces.integer == 2)
10153         {
10154                 const int *e;
10155                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10156                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10157                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10158                 {
10159                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10160                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10161                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10162                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10163                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10164                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10165                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10166                 }
10167                 R_Mesh_PrepareVertices_Generic_Unlock();
10168                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10169         }
10170         else
10171         {
10172                 int texturesurfaceindex;
10173                 int k;
10174                 const msurface_t *surface;
10175                 float surfacecolor4f[4];
10176                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10177                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10178                 vi = 0;
10179                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10180                 {
10181                         surface = texturesurfacelist[texturesurfaceindex];
10182                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10183                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10184                         for (j = 0;j < surface->num_vertices;j++)
10185                         {
10186                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10187                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10188                                 vi++;
10189                         }
10190                 }
10191                 R_Mesh_PrepareVertices_Generic_Unlock();
10192                 RSurf_DrawBatch();
10193         }
10194 }
10195
10196 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10197 {
10198         CHECKGLERROR
10199         RSurf_SetupDepthAndCulling();
10200         if (r_showsurfaces.integer)
10201         {
10202                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10203                 return;
10204         }
10205         switch (vid.renderpath)
10206         {
10207         case RENDERPATH_GL20:
10208         case RENDERPATH_D3D9:
10209         case RENDERPATH_D3D10:
10210         case RENDERPATH_D3D11:
10211         case RENDERPATH_SOFT:
10212         case RENDERPATH_GLES2:
10213                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10214                 break;
10215         case RENDERPATH_GL13:
10216         case RENDERPATH_GLES1:
10217                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10218                 break;
10219         case RENDERPATH_GL11:
10220                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10221                 break;
10222         }
10223         CHECKGLERROR
10224 }
10225
10226 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10227 {
10228         CHECKGLERROR
10229         RSurf_SetupDepthAndCulling();
10230         if (r_showsurfaces.integer)
10231         {
10232                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10233                 return;
10234         }
10235         switch (vid.renderpath)
10236         {
10237         case RENDERPATH_GL20:
10238         case RENDERPATH_D3D9:
10239         case RENDERPATH_D3D10:
10240         case RENDERPATH_D3D11:
10241         case RENDERPATH_SOFT:
10242         case RENDERPATH_GLES2:
10243                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10244                 break;
10245         case RENDERPATH_GL13:
10246         case RENDERPATH_GLES1:
10247                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10248                 break;
10249         case RENDERPATH_GL11:
10250                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10251                 break;
10252         }
10253         CHECKGLERROR
10254 }
10255
10256 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10257 {
10258         int i, j;
10259         int texturenumsurfaces, endsurface;
10260         texture_t *texture;
10261         const msurface_t *surface;
10262         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10263
10264         // if the model is static it doesn't matter what value we give for
10265         // wantnormals and wanttangents, so this logic uses only rules applicable
10266         // to a model, knowing that they are meaningless otherwise
10267         if (ent == r_refdef.scene.worldentity)
10268                 RSurf_ActiveWorldEntity();
10269         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10270                 RSurf_ActiveModelEntity(ent, false, false, false);
10271         else
10272         {
10273                 switch (vid.renderpath)
10274                 {
10275                 case RENDERPATH_GL20:
10276                 case RENDERPATH_D3D9:
10277                 case RENDERPATH_D3D10:
10278                 case RENDERPATH_D3D11:
10279                 case RENDERPATH_SOFT:
10280                 case RENDERPATH_GLES2:
10281                         RSurf_ActiveModelEntity(ent, true, true, false);
10282                         break;
10283                 case RENDERPATH_GL11:
10284                 case RENDERPATH_GL13:
10285                 case RENDERPATH_GLES1:
10286                         RSurf_ActiveModelEntity(ent, true, false, false);
10287                         break;
10288                 }
10289         }
10290
10291         if (r_transparentdepthmasking.integer)
10292         {
10293                 qboolean setup = false;
10294                 for (i = 0;i < numsurfaces;i = j)
10295                 {
10296                         j = i + 1;
10297                         surface = rsurface.modelsurfaces + surfacelist[i];
10298                         texture = surface->texture;
10299                         rsurface.texture = R_GetCurrentTexture(texture);
10300                         rsurface.lightmaptexture = NULL;
10301                         rsurface.deluxemaptexture = NULL;
10302                         rsurface.uselightmaptexture = false;
10303                         // scan ahead until we find a different texture
10304                         endsurface = min(i + 1024, numsurfaces);
10305                         texturenumsurfaces = 0;
10306                         texturesurfacelist[texturenumsurfaces++] = surface;
10307                         for (;j < endsurface;j++)
10308                         {
10309                                 surface = rsurface.modelsurfaces + surfacelist[j];
10310                                 if (texture != surface->texture)
10311                                         break;
10312                                 texturesurfacelist[texturenumsurfaces++] = surface;
10313                         }
10314                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10315                                 continue;
10316                         // render the range of surfaces as depth
10317                         if (!setup)
10318                         {
10319                                 setup = true;
10320                                 GL_ColorMask(0,0,0,0);
10321                                 GL_Color(1,1,1,1);
10322                                 GL_DepthTest(true);
10323                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10324                                 GL_DepthMask(true);
10325 //                              R_Mesh_ResetTextureState();
10326                                 R_SetupShader_DepthOrShadow(false);
10327                         }
10328                         RSurf_SetupDepthAndCulling();
10329                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10330                         if (rsurface.batchvertex3fbuffer)
10331                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10332                         else
10333                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10334                         RSurf_DrawBatch();
10335                 }
10336                 if (setup)
10337                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10338         }
10339
10340         for (i = 0;i < numsurfaces;i = j)
10341         {
10342                 j = i + 1;
10343                 surface = rsurface.modelsurfaces + surfacelist[i];
10344                 texture = surface->texture;
10345                 rsurface.texture = R_GetCurrentTexture(texture);
10346                 // scan ahead until we find a different texture
10347                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10348                 texturenumsurfaces = 0;
10349                 texturesurfacelist[texturenumsurfaces++] = surface;
10350                 if(FAKELIGHT_ENABLED)
10351                 {
10352                         rsurface.lightmaptexture = NULL;
10353                         rsurface.deluxemaptexture = NULL;
10354                         rsurface.uselightmaptexture = false;
10355                         for (;j < endsurface;j++)
10356                         {
10357                                 surface = rsurface.modelsurfaces + surfacelist[j];
10358                                 if (texture != surface->texture)
10359                                         break;
10360                                 texturesurfacelist[texturenumsurfaces++] = surface;
10361                         }
10362                 }
10363                 else
10364                 {
10365                         rsurface.lightmaptexture = surface->lightmaptexture;
10366                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10367                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10368                         for (;j < endsurface;j++)
10369                         {
10370                                 surface = rsurface.modelsurfaces + surfacelist[j];
10371                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10372                                         break;
10373                                 texturesurfacelist[texturenumsurfaces++] = surface;
10374                         }
10375                 }
10376                 // render the range of surfaces
10377                 if (ent == r_refdef.scene.worldentity)
10378                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10379                 else
10380                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10381         }
10382         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10383 }
10384
10385 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10386 {
10387         // transparent surfaces get pushed off into the transparent queue
10388         int surfacelistindex;
10389         const msurface_t *surface;
10390         vec3_t tempcenter, center;
10391         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10392         {
10393                 surface = texturesurfacelist[surfacelistindex];
10394                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10395                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10396                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10397                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10398                 if (queueentity->transparent_offset) // transparent offset
10399                 {
10400                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10401                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10402                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10403                 }
10404                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10405         }
10406 }
10407
10408 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10409 {
10410         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10411                 return;
10412         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10413                 return;
10414         RSurf_SetupDepthAndCulling();
10415         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10416         if (rsurface.batchvertex3fbuffer)
10417                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10418         else
10419                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10420         RSurf_DrawBatch();
10421 }
10422
10423 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10424 {
10425         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10426         CHECKGLERROR
10427         if (depthonly)
10428                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10429         else if (prepass)
10430         {
10431                 if (!rsurface.texture->currentnumlayers)
10432                         return;
10433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10434                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10435                 else
10436                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10437         }
10438         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10439                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10440         else if (!rsurface.texture->currentnumlayers)
10441                 return;
10442         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10443         {
10444                 // in the deferred case, transparent surfaces were queued during prepass
10445                 if (!r_shadow_usingdeferredprepass)
10446                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10447         }
10448         else
10449         {
10450                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10451                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10452         }
10453         CHECKGLERROR
10454 }
10455
10456 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10457 {
10458         int i, j;
10459         texture_t *texture;
10460         R_FrameData_SetMark();
10461         // break the surface list down into batches by texture and use of lightmapping
10462         for (i = 0;i < numsurfaces;i = j)
10463         {
10464                 j = i + 1;
10465                 // texture is the base texture pointer, rsurface.texture is the
10466                 // current frame/skin the texture is directing us to use (for example
10467                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10468                 // use skin 1 instead)
10469                 texture = surfacelist[i]->texture;
10470                 rsurface.texture = R_GetCurrentTexture(texture);
10471                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10472                 {
10473                         // if this texture is not the kind we want, skip ahead to the next one
10474                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10475                                 ;
10476                         continue;
10477                 }
10478                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10479                 {
10480                         rsurface.lightmaptexture = NULL;
10481                         rsurface.deluxemaptexture = NULL;
10482                         rsurface.uselightmaptexture = false;
10483                         // simply scan ahead until we find a different texture or lightmap state
10484                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10485                                 ;
10486                 }
10487                 else
10488                 {
10489                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10490                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10491                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10492                         // simply scan ahead until we find a different texture or lightmap state
10493                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10494                                 ;
10495                 }
10496                 // render the range of surfaces
10497                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10498         }
10499         R_FrameData_ReturnToMark();
10500 }
10501
10502 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10503 {
10504         CHECKGLERROR
10505         if (depthonly)
10506                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10507         else if (prepass)
10508         {
10509                 if (!rsurface.texture->currentnumlayers)
10510                         return;
10511                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10512                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10513                 else
10514                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10515         }
10516         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10517                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10518         else if (!rsurface.texture->currentnumlayers)
10519                 return;
10520         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10521         {
10522                 // in the deferred case, transparent surfaces were queued during prepass
10523                 if (!r_shadow_usingdeferredprepass)
10524                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10525         }
10526         else
10527         {
10528                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10529                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10530         }
10531         CHECKGLERROR
10532 }
10533
10534 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10535 {
10536         int i, j;
10537         texture_t *texture;
10538         R_FrameData_SetMark();
10539         // break the surface list down into batches by texture and use of lightmapping
10540         for (i = 0;i < numsurfaces;i = j)
10541         {
10542                 j = i + 1;
10543                 // texture is the base texture pointer, rsurface.texture is the
10544                 // current frame/skin the texture is directing us to use (for example
10545                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10546                 // use skin 1 instead)
10547                 texture = surfacelist[i]->texture;
10548                 rsurface.texture = R_GetCurrentTexture(texture);
10549                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10550                 {
10551                         // if this texture is not the kind we want, skip ahead to the next one
10552                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10553                                 ;
10554                         continue;
10555                 }
10556                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10557                 {
10558                         rsurface.lightmaptexture = NULL;
10559                         rsurface.deluxemaptexture = NULL;
10560                         rsurface.uselightmaptexture = false;
10561                         // simply scan ahead until we find a different texture or lightmap state
10562                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10563                                 ;
10564                 }
10565                 else
10566                 {
10567                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10568                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10569                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10570                         // simply scan ahead until we find a different texture or lightmap state
10571                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10572                                 ;
10573                 }
10574                 // render the range of surfaces
10575                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10576         }
10577         R_FrameData_ReturnToMark();
10578 }
10579
10580 float locboxvertex3f[6*4*3] =
10581 {
10582         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10583         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10584         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10585         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10586         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10587         1,0,0, 0,0,0, 0,1,0, 1,1,0
10588 };
10589
10590 unsigned short locboxelements[6*2*3] =
10591 {
10592          0, 1, 2, 0, 2, 3,
10593          4, 5, 6, 4, 6, 7,
10594          8, 9,10, 8,10,11,
10595         12,13,14, 12,14,15,
10596         16,17,18, 16,18,19,
10597         20,21,22, 20,22,23
10598 };
10599
10600 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10601 {
10602         int i, j;
10603         cl_locnode_t *loc = (cl_locnode_t *)ent;
10604         vec3_t mins, size;
10605         float vertex3f[6*4*3];
10606         CHECKGLERROR
10607         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10608         GL_DepthMask(false);
10609         GL_DepthRange(0, 1);
10610         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10611         GL_DepthTest(true);
10612         GL_CullFace(GL_NONE);
10613         R_EntityMatrix(&identitymatrix);
10614
10615 //      R_Mesh_ResetTextureState();
10616
10617         i = surfacelist[0];
10618         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10619                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10620                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10621                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10622
10623         if (VectorCompare(loc->mins, loc->maxs))
10624         {
10625                 VectorSet(size, 2, 2, 2);
10626                 VectorMA(loc->mins, -0.5f, size, mins);
10627         }
10628         else
10629         {
10630                 VectorCopy(loc->mins, mins);
10631                 VectorSubtract(loc->maxs, loc->mins, size);
10632         }
10633
10634         for (i = 0;i < 6*4*3;)
10635                 for (j = 0;j < 3;j++, i++)
10636                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10637
10638         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10639         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10640         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10641 }
10642
10643 void R_DrawLocs(void)
10644 {
10645         int index;
10646         cl_locnode_t *loc, *nearestloc;
10647         vec3_t center;
10648         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10649         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10650         {
10651                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10652                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10653         }
10654 }
10655
10656 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10657 {
10658         if (decalsystem->decals)
10659                 Mem_Free(decalsystem->decals);
10660         memset(decalsystem, 0, sizeof(*decalsystem));
10661 }
10662
10663 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)
10664 {
10665         tridecal_t *decal;
10666         tridecal_t *decals;
10667         int i;
10668
10669         // expand or initialize the system
10670         if (decalsystem->maxdecals <= decalsystem->numdecals)
10671         {
10672                 decalsystem_t old = *decalsystem;
10673                 qboolean useshortelements;
10674                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10675                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10676                 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)));
10677                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10678                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10679                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10680                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10681                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10682                 if (decalsystem->numdecals)
10683                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10684                 if (old.decals)
10685                         Mem_Free(old.decals);
10686                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10687                         decalsystem->element3i[i] = i;
10688                 if (useshortelements)
10689                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10690                                 decalsystem->element3s[i] = i;
10691         }
10692
10693         // grab a decal and search for another free slot for the next one
10694         decals = decalsystem->decals;
10695         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10696         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10697                 ;
10698         decalsystem->freedecal = i;
10699         if (decalsystem->numdecals <= i)
10700                 decalsystem->numdecals = i + 1;
10701
10702         // initialize the decal
10703         decal->lived = 0;
10704         decal->triangleindex = triangleindex;
10705         decal->surfaceindex = surfaceindex;
10706         decal->decalsequence = decalsequence;
10707         decal->color4f[0][0] = c0[0];
10708         decal->color4f[0][1] = c0[1];
10709         decal->color4f[0][2] = c0[2];
10710         decal->color4f[0][3] = 1;
10711         decal->color4f[1][0] = c1[0];
10712         decal->color4f[1][1] = c1[1];
10713         decal->color4f[1][2] = c1[2];
10714         decal->color4f[1][3] = 1;
10715         decal->color4f[2][0] = c2[0];
10716         decal->color4f[2][1] = c2[1];
10717         decal->color4f[2][2] = c2[2];
10718         decal->color4f[2][3] = 1;
10719         decal->vertex3f[0][0] = v0[0];
10720         decal->vertex3f[0][1] = v0[1];
10721         decal->vertex3f[0][2] = v0[2];
10722         decal->vertex3f[1][0] = v1[0];
10723         decal->vertex3f[1][1] = v1[1];
10724         decal->vertex3f[1][2] = v1[2];
10725         decal->vertex3f[2][0] = v2[0];
10726         decal->vertex3f[2][1] = v2[1];
10727         decal->vertex3f[2][2] = v2[2];
10728         decal->texcoord2f[0][0] = t0[0];
10729         decal->texcoord2f[0][1] = t0[1];
10730         decal->texcoord2f[1][0] = t1[0];
10731         decal->texcoord2f[1][1] = t1[1];
10732         decal->texcoord2f[2][0] = t2[0];
10733         decal->texcoord2f[2][1] = t2[1];
10734         TriangleNormal(v0, v1, v2, decal->plane);
10735         VectorNormalize(decal->plane);
10736         decal->plane[3] = DotProduct(v0, decal->plane);
10737 }
10738
10739 extern cvar_t cl_decals_bias;
10740 extern cvar_t cl_decals_models;
10741 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10742 // baseparms, parms, temps
10743 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)
10744 {
10745         int cornerindex;
10746         int index;
10747         float v[9][3];
10748         const float *vertex3f;
10749         const float *normal3f;
10750         int numpoints;
10751         float points[2][9][3];
10752         float temp[3];
10753         float tc[9][2];
10754         float f;
10755         float c[9][4];
10756         const int *e;
10757
10758         e = rsurface.modelelement3i + 3*triangleindex;
10759
10760         vertex3f = rsurface.modelvertex3f;
10761         normal3f = rsurface.modelnormal3f;
10762
10763         if (normal3f)
10764         {
10765                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10766                 {
10767                         index = 3*e[cornerindex];
10768                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10769                 }
10770         }
10771         else
10772         {
10773                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10774                 {
10775                         index = 3*e[cornerindex];
10776                         VectorCopy(vertex3f + index, v[cornerindex]);
10777                 }
10778         }
10779
10780         // cull backfaces
10781         //TriangleNormal(v[0], v[1], v[2], normal);
10782         //if (DotProduct(normal, localnormal) < 0.0f)
10783         //      continue;
10784         // clip by each of the box planes formed from the projection matrix
10785         // if anything survives, we emit the decal
10786         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]);
10787         if (numpoints < 3)
10788                 return;
10789         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]);
10790         if (numpoints < 3)
10791                 return;
10792         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]);
10793         if (numpoints < 3)
10794                 return;
10795         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]);
10796         if (numpoints < 3)
10797                 return;
10798         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]);
10799         if (numpoints < 3)
10800                 return;
10801         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]);
10802         if (numpoints < 3)
10803                 return;
10804         // some part of the triangle survived, so we have to accept it...
10805         if (dynamic)
10806         {
10807                 // dynamic always uses the original triangle
10808                 numpoints = 3;
10809                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10810                 {
10811                         index = 3*e[cornerindex];
10812                         VectorCopy(vertex3f + index, v[cornerindex]);
10813                 }
10814         }
10815         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10816         {
10817                 // convert vertex positions to texcoords
10818                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10819                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10820                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10821                 // calculate distance fade from the projection origin
10822                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10823                 f = bound(0.0f, f, 1.0f);
10824                 c[cornerindex][0] = r * f;
10825                 c[cornerindex][1] = g * f;
10826                 c[cornerindex][2] = b * f;
10827                 c[cornerindex][3] = 1.0f;
10828                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10829         }
10830         if (dynamic)
10831                 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);
10832         else
10833                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10834                         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);
10835 }
10836 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)
10837 {
10838         matrix4x4_t projection;
10839         decalsystem_t *decalsystem;
10840         qboolean dynamic;
10841         dp_model_t *model;
10842         const msurface_t *surface;
10843         const msurface_t *surfaces;
10844         const int *surfacelist;
10845         const texture_t *texture;
10846         int numtriangles;
10847         int numsurfacelist;
10848         int surfacelistindex;
10849         int surfaceindex;
10850         int triangleindex;
10851         float localorigin[3];
10852         float localnormal[3];
10853         float localmins[3];
10854         float localmaxs[3];
10855         float localsize;
10856         //float normal[3];
10857         float planes[6][4];
10858         float angles[3];
10859         bih_t *bih;
10860         int bih_triangles_count;
10861         int bih_triangles[256];
10862         int bih_surfaces[256];
10863
10864         decalsystem = &ent->decalsystem;
10865         model = ent->model;
10866         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10867         {
10868                 R_DecalSystem_Reset(&ent->decalsystem);
10869                 return;
10870         }
10871
10872         if (!model->brush.data_leafs && !cl_decals_models.integer)
10873         {
10874                 if (decalsystem->model)
10875                         R_DecalSystem_Reset(decalsystem);
10876                 return;
10877         }
10878
10879         if (decalsystem->model != model)
10880                 R_DecalSystem_Reset(decalsystem);
10881         decalsystem->model = model;
10882
10883         RSurf_ActiveModelEntity(ent, true, false, false);
10884
10885         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10886         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10887         VectorNormalize(localnormal);
10888         localsize = worldsize*rsurface.inversematrixscale;
10889         localmins[0] = localorigin[0] - localsize;
10890         localmins[1] = localorigin[1] - localsize;
10891         localmins[2] = localorigin[2] - localsize;
10892         localmaxs[0] = localorigin[0] + localsize;
10893         localmaxs[1] = localorigin[1] + localsize;
10894         localmaxs[2] = localorigin[2] + localsize;
10895
10896         //VectorCopy(localnormal, planes[4]);
10897         //VectorVectors(planes[4], planes[2], planes[0]);
10898         AnglesFromVectors(angles, localnormal, NULL, false);
10899         AngleVectors(angles, planes[0], planes[2], planes[4]);
10900         VectorNegate(planes[0], planes[1]);
10901         VectorNegate(planes[2], planes[3]);
10902         VectorNegate(planes[4], planes[5]);
10903         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10904         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10905         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10906         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10907         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10908         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10909
10910 #if 1
10911 // works
10912 {
10913         matrix4x4_t forwardprojection;
10914         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10915         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10916 }
10917 #else
10918 // broken
10919 {
10920         float projectionvector[4][3];
10921         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10922         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10923         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10924         projectionvector[0][0] = planes[0][0] * ilocalsize;
10925         projectionvector[0][1] = planes[1][0] * ilocalsize;
10926         projectionvector[0][2] = planes[2][0] * ilocalsize;
10927         projectionvector[1][0] = planes[0][1] * ilocalsize;
10928         projectionvector[1][1] = planes[1][1] * ilocalsize;
10929         projectionvector[1][2] = planes[2][1] * ilocalsize;
10930         projectionvector[2][0] = planes[0][2] * ilocalsize;
10931         projectionvector[2][1] = planes[1][2] * ilocalsize;
10932         projectionvector[2][2] = planes[2][2] * ilocalsize;
10933         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10934         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10935         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10936         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10937 }
10938 #endif
10939
10940         dynamic = model->surfmesh.isanimated;
10941         numsurfacelist = model->nummodelsurfaces;
10942         surfacelist = model->sortedmodelsurfaces;
10943         surfaces = model->data_surfaces;
10944
10945         bih = NULL;
10946         bih_triangles_count = -1;
10947         if(!dynamic)
10948         {
10949                 if(model->render_bih.numleafs)
10950                         bih = &model->render_bih;
10951                 else if(model->collision_bih.numleafs)
10952                         bih = &model->collision_bih;
10953         }
10954         if(bih)
10955                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10956         if(bih_triangles_count == 0)
10957                 return;
10958         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10959                 return;
10960         if(bih_triangles_count > 0)
10961         {
10962                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10963                 {
10964                         surfaceindex = bih_surfaces[triangleindex];
10965                         surface = surfaces + surfaceindex;
10966                         texture = surface->texture;
10967                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10968                                 continue;
10969                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10970                                 continue;
10971                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10972                 }
10973         }
10974         else
10975         {
10976                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10977                 {
10978                         surfaceindex = surfacelist[surfacelistindex];
10979                         surface = surfaces + surfaceindex;
10980                         // check cull box first because it rejects more than any other check
10981                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10982                                 continue;
10983                         // skip transparent surfaces
10984                         texture = surface->texture;
10985                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10986                                 continue;
10987                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10988                                 continue;
10989                         numtriangles = surface->num_triangles;
10990                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10991                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10992                 }
10993         }
10994 }
10995
10996 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10997 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)
10998 {
10999         int renderentityindex;
11000         float worldmins[3];
11001         float worldmaxs[3];
11002         entity_render_t *ent;
11003
11004         if (!cl_decals_newsystem.integer)
11005                 return;
11006
11007         worldmins[0] = worldorigin[0] - worldsize;
11008         worldmins[1] = worldorigin[1] - worldsize;
11009         worldmins[2] = worldorigin[2] - worldsize;
11010         worldmaxs[0] = worldorigin[0] + worldsize;
11011         worldmaxs[1] = worldorigin[1] + worldsize;
11012         worldmaxs[2] = worldorigin[2] + worldsize;
11013
11014         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11015
11016         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11017         {
11018                 ent = r_refdef.scene.entities[renderentityindex];
11019                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11020                         continue;
11021
11022                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11023         }
11024 }
11025
11026 typedef struct r_decalsystem_splatqueue_s
11027 {
11028         vec3_t worldorigin;
11029         vec3_t worldnormal;
11030         float color[4];
11031         float tcrange[4];
11032         float worldsize;
11033         int decalsequence;
11034 }
11035 r_decalsystem_splatqueue_t;
11036
11037 int r_decalsystem_numqueued = 0;
11038 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11039
11040 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)
11041 {
11042         r_decalsystem_splatqueue_t *queue;
11043
11044         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11045                 return;
11046
11047         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11048         VectorCopy(worldorigin, queue->worldorigin);
11049         VectorCopy(worldnormal, queue->worldnormal);
11050         Vector4Set(queue->color, r, g, b, a);
11051         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11052         queue->worldsize = worldsize;
11053         queue->decalsequence = cl.decalsequence++;
11054 }
11055
11056 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11057 {
11058         int i;
11059         r_decalsystem_splatqueue_t *queue;
11060
11061         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11062                 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);
11063         r_decalsystem_numqueued = 0;
11064 }
11065
11066 extern cvar_t cl_decals_max;
11067 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11068 {
11069         int i;
11070         decalsystem_t *decalsystem = &ent->decalsystem;
11071         int numdecals;
11072         int killsequence;
11073         tridecal_t *decal;
11074         float frametime;
11075         float lifetime;
11076
11077         if (!decalsystem->numdecals)
11078                 return;
11079
11080         if (r_showsurfaces.integer)
11081                 return;
11082
11083         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11084         {
11085                 R_DecalSystem_Reset(decalsystem);
11086                 return;
11087         }
11088
11089         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11090         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11091
11092         if (decalsystem->lastupdatetime)
11093                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11094         else
11095                 frametime = 0;
11096         decalsystem->lastupdatetime = r_refdef.scene.time;
11097         decal = decalsystem->decals;
11098         numdecals = decalsystem->numdecals;
11099
11100         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11101         {
11102                 if (decal->color4f[0][3])
11103                 {
11104                         decal->lived += frametime;
11105                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11106                         {
11107                                 memset(decal, 0, sizeof(*decal));
11108                                 if (decalsystem->freedecal > i)
11109                                         decalsystem->freedecal = i;
11110                         }
11111                 }
11112         }
11113         decal = decalsystem->decals;
11114         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11115                 numdecals--;
11116
11117         // collapse the array by shuffling the tail decals into the gaps
11118         for (;;)
11119         {
11120                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11121                         decalsystem->freedecal++;
11122                 if (decalsystem->freedecal == numdecals)
11123                         break;
11124                 decal[decalsystem->freedecal] = decal[--numdecals];
11125         }
11126
11127         decalsystem->numdecals = numdecals;
11128
11129         if (numdecals <= 0)
11130         {
11131                 // if there are no decals left, reset decalsystem
11132                 R_DecalSystem_Reset(decalsystem);
11133         }
11134 }
11135
11136 extern skinframe_t *decalskinframe;
11137 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11138 {
11139         int i;
11140         decalsystem_t *decalsystem = &ent->decalsystem;
11141         int numdecals;
11142         tridecal_t *decal;
11143         float faderate;
11144         float alpha;
11145         float *v3f;
11146         float *c4f;
11147         float *t2f;
11148         const int *e;
11149         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11150         int numtris = 0;
11151
11152         numdecals = decalsystem->numdecals;
11153         if (!numdecals)
11154                 return;
11155
11156         if (r_showsurfaces.integer)
11157                 return;
11158
11159         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11160         {
11161                 R_DecalSystem_Reset(decalsystem);
11162                 return;
11163         }
11164
11165         // if the model is static it doesn't matter what value we give for
11166         // wantnormals and wanttangents, so this logic uses only rules applicable
11167         // to a model, knowing that they are meaningless otherwise
11168         if (ent == r_refdef.scene.worldentity)
11169                 RSurf_ActiveWorldEntity();
11170         else
11171                 RSurf_ActiveModelEntity(ent, false, false, false);
11172
11173         decalsystem->lastupdatetime = r_refdef.scene.time;
11174         decal = decalsystem->decals;
11175
11176         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11177
11178         // update vertex positions for animated models
11179         v3f = decalsystem->vertex3f;
11180         c4f = decalsystem->color4f;
11181         t2f = decalsystem->texcoord2f;
11182         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11183         {
11184                 if (!decal->color4f[0][3])
11185                         continue;
11186
11187                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11188                         continue;
11189
11190                 // skip backfaces
11191                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11192                         continue;
11193
11194                 // update color values for fading decals
11195                 if (decal->lived >= cl_decals_time.value)
11196                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11197                 else
11198                         alpha = 1.0f;
11199
11200                 c4f[ 0] = decal->color4f[0][0] * alpha;
11201                 c4f[ 1] = decal->color4f[0][1] * alpha;
11202                 c4f[ 2] = decal->color4f[0][2] * alpha;
11203                 c4f[ 3] = 1;
11204                 c4f[ 4] = decal->color4f[1][0] * alpha;
11205                 c4f[ 5] = decal->color4f[1][1] * alpha;
11206                 c4f[ 6] = decal->color4f[1][2] * alpha;
11207                 c4f[ 7] = 1;
11208                 c4f[ 8] = decal->color4f[2][0] * alpha;
11209                 c4f[ 9] = decal->color4f[2][1] * alpha;
11210                 c4f[10] = decal->color4f[2][2] * alpha;
11211                 c4f[11] = 1;
11212
11213                 t2f[0] = decal->texcoord2f[0][0];
11214                 t2f[1] = decal->texcoord2f[0][1];
11215                 t2f[2] = decal->texcoord2f[1][0];
11216                 t2f[3] = decal->texcoord2f[1][1];
11217                 t2f[4] = decal->texcoord2f[2][0];
11218                 t2f[5] = decal->texcoord2f[2][1];
11219
11220                 // update vertex positions for animated models
11221                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11222                 {
11223                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11224                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11225                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11226                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11227                 }
11228                 else
11229                 {
11230                         VectorCopy(decal->vertex3f[0], v3f);
11231                         VectorCopy(decal->vertex3f[1], v3f + 3);
11232                         VectorCopy(decal->vertex3f[2], v3f + 6);
11233                 }
11234
11235                 if (r_refdef.fogenabled)
11236                 {
11237                         alpha = RSurf_FogVertex(v3f);
11238                         VectorScale(c4f, alpha, c4f);
11239                         alpha = RSurf_FogVertex(v3f + 3);
11240                         VectorScale(c4f + 4, alpha, c4f + 4);
11241                         alpha = RSurf_FogVertex(v3f + 6);
11242                         VectorScale(c4f + 8, alpha, c4f + 8);
11243                 }
11244
11245                 v3f += 9;
11246                 c4f += 12;
11247                 t2f += 6;
11248                 numtris++;
11249         }
11250
11251         if (numtris > 0)
11252         {
11253                 r_refdef.stats.drawndecals += numtris;
11254
11255                 // now render the decals all at once
11256                 // (this assumes they all use one particle font texture!)
11257                 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);
11258 //              R_Mesh_ResetTextureState();
11259                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11260                 GL_DepthMask(false);
11261                 GL_DepthRange(0, 1);
11262                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11263                 GL_DepthTest(true);
11264                 GL_CullFace(GL_NONE);
11265                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11266                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11267                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11268         }
11269 }
11270
11271 static void R_DrawModelDecals(void)
11272 {
11273         int i, numdecals;
11274
11275         // fade faster when there are too many decals
11276         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11277         for (i = 0;i < r_refdef.scene.numentities;i++)
11278                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11279
11280         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11281         for (i = 0;i < r_refdef.scene.numentities;i++)
11282                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11283                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11284
11285         R_DecalSystem_ApplySplatEntitiesQueue();
11286
11287         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11288         for (i = 0;i < r_refdef.scene.numentities;i++)
11289                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11290
11291         r_refdef.stats.totaldecals += numdecals;
11292
11293         if (r_showsurfaces.integer)
11294                 return;
11295
11296         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11297
11298         for (i = 0;i < r_refdef.scene.numentities;i++)
11299         {
11300                 if (!r_refdef.viewcache.entityvisible[i])
11301                         continue;
11302                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11303                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11304         }
11305 }
11306
11307 extern cvar_t mod_collision_bih;
11308 void R_DrawDebugModel(void)
11309 {
11310         entity_render_t *ent = rsurface.entity;
11311         int i, j, k, l, flagsmask;
11312         const msurface_t *surface;
11313         dp_model_t *model = ent->model;
11314         vec3_t v;
11315
11316         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11317                 return;
11318
11319         if (r_showoverdraw.value > 0)
11320         {
11321                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11322                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11323                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11324                 GL_DepthTest(false);
11325                 GL_DepthMask(false);
11326                 GL_DepthRange(0, 1);
11327                 GL_BlendFunc(GL_ONE, GL_ONE);
11328                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11329                 {
11330                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11331                                 continue;
11332                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11333                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11334                         {
11335                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11336                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11337                                 if (!rsurface.texture->currentlayers->depthmask)
11338                                         GL_Color(c, 0, 0, 1.0f);
11339                                 else if (ent == r_refdef.scene.worldentity)
11340                                         GL_Color(c, c, c, 1.0f);
11341                                 else
11342                                         GL_Color(0, c, 0, 1.0f);
11343                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11344                                 RSurf_DrawBatch();
11345                         }
11346                 }
11347                 rsurface.texture = NULL;
11348         }
11349
11350         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11351
11352 //      R_Mesh_ResetTextureState();
11353         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11354         GL_DepthRange(0, 1);
11355         GL_DepthTest(!r_showdisabledepthtest.integer);
11356         GL_DepthMask(false);
11357         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11358
11359         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11360         {
11361                 int triangleindex;
11362                 int bihleafindex;
11363                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11364                 const q3mbrush_t *brush;
11365                 const bih_t *bih = &model->collision_bih;
11366                 const bih_leaf_t *bihleaf;
11367                 float vertex3f[3][3];
11368                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11369                 cullbox = false;
11370                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11371                 {
11372                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11373                                 continue;
11374                         switch (bihleaf->type)
11375                         {
11376                         case BIH_BRUSH:
11377                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11378                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11379                                 {
11380                                         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);
11381                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11382                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11383                                 }
11384                                 break;
11385                         case BIH_COLLISIONTRIANGLE:
11386                                 triangleindex = bihleaf->itemindex;
11387                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11388                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11389                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11390                                 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);
11391                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11392                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11393                                 break;
11394                         case BIH_RENDERTRIANGLE:
11395                                 triangleindex = bihleaf->itemindex;
11396                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11397                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11398                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11399                                 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);
11400                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11401                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11402                                 break;
11403                         }
11404                 }
11405         }
11406
11407         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11408
11409 #ifndef USE_GLES2
11410         if (r_showtris.integer && qglPolygonMode)
11411         {
11412                 if (r_showdisabledepthtest.integer)
11413                 {
11414                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11415                         GL_DepthMask(false);
11416                 }
11417                 else
11418                 {
11419                         GL_BlendFunc(GL_ONE, GL_ZERO);
11420                         GL_DepthMask(true);
11421                 }
11422                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11423                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11424                 {
11425                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11426                                 continue;
11427                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11428                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11429                         {
11430                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11431                                 if (!rsurface.texture->currentlayers->depthmask)
11432                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11433                                 else if (ent == r_refdef.scene.worldentity)
11434                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11435                                 else
11436                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11437                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11438                                 RSurf_DrawBatch();
11439                         }
11440                 }
11441                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11442                 rsurface.texture = NULL;
11443         }
11444
11445         if (r_shownormals.value != 0 && qglBegin)
11446         {
11447                 if (r_showdisabledepthtest.integer)
11448                 {
11449                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11450                         GL_DepthMask(false);
11451                 }
11452                 else
11453                 {
11454                         GL_BlendFunc(GL_ONE, GL_ZERO);
11455                         GL_DepthMask(true);
11456                 }
11457                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11458                 {
11459                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11460                                 continue;
11461                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11462                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11463                         {
11464                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11465                                 qglBegin(GL_LINES);
11466                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11467                                 {
11468                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11469                                         {
11470                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11471                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11472                                                 qglVertex3f(v[0], v[1], v[2]);
11473                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11474                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11475                                                 qglVertex3f(v[0], v[1], v[2]);
11476                                         }
11477                                 }
11478                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11479                                 {
11480                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11481                                         {
11482                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11483                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11484                                                 qglVertex3f(v[0], v[1], v[2]);
11485                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11486                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11487                                                 qglVertex3f(v[0], v[1], v[2]);
11488                                         }
11489                                 }
11490                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11491                                 {
11492                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11493                                         {
11494                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11495                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11496                                                 qglVertex3f(v[0], v[1], v[2]);
11497                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11498                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11499                                                 qglVertex3f(v[0], v[1], v[2]);
11500                                         }
11501                                 }
11502                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11503                                 {
11504                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11505                                         {
11506                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11507                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11508                                                 qglVertex3f(v[0], v[1], v[2]);
11509                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11510                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11511                                                 qglVertex3f(v[0], v[1], v[2]);
11512                                         }
11513                                 }
11514                                 qglEnd();
11515                                 CHECKGLERROR
11516                         }
11517                 }
11518                 rsurface.texture = NULL;
11519         }
11520 #endif
11521 }
11522
11523 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11524 int r_maxsurfacelist = 0;
11525 const msurface_t **r_surfacelist = NULL;
11526 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11527 {
11528         int i, j, endj, flagsmask;
11529         dp_model_t *model = r_refdef.scene.worldmodel;
11530         msurface_t *surfaces;
11531         unsigned char *update;
11532         int numsurfacelist = 0;
11533         if (model == NULL)
11534                 return;
11535
11536         if (r_maxsurfacelist < model->num_surfaces)
11537         {
11538                 r_maxsurfacelist = model->num_surfaces;
11539                 if (r_surfacelist)
11540                         Mem_Free((msurface_t**)r_surfacelist);
11541                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11542         }
11543
11544         RSurf_ActiveWorldEntity();
11545
11546         surfaces = model->data_surfaces;
11547         update = model->brushq1.lightmapupdateflags;
11548
11549         // update light styles on this submodel
11550         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11551         {
11552                 model_brush_lightstyleinfo_t *style;
11553                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11554                 {
11555                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11556                         {
11557                                 int *list = style->surfacelist;
11558                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11559                                 for (j = 0;j < style->numsurfaces;j++)
11560                                         update[list[j]] = true;
11561                         }
11562                 }
11563         }
11564
11565         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11566
11567         if (debug)
11568         {
11569                 R_DrawDebugModel();
11570                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11571                 return;
11572         }
11573
11574         rsurface.lightmaptexture = NULL;
11575         rsurface.deluxemaptexture = NULL;
11576         rsurface.uselightmaptexture = false;
11577         rsurface.texture = NULL;
11578         rsurface.rtlight = NULL;
11579         numsurfacelist = 0;
11580         // add visible surfaces to draw list
11581         for (i = 0;i < model->nummodelsurfaces;i++)
11582         {
11583                 j = model->sortedmodelsurfaces[i];
11584                 if (r_refdef.viewcache.world_surfacevisible[j])
11585                         r_surfacelist[numsurfacelist++] = surfaces + j;
11586         }
11587         // update lightmaps if needed
11588         if (model->brushq1.firstrender)
11589         {
11590                 model->brushq1.firstrender = false;
11591                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11592                         if (update[j])
11593                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11594         }
11595         else if (update)
11596         {
11597                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11598                         if (r_refdef.viewcache.world_surfacevisible[j])
11599                                 if (update[j])
11600                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11601         }
11602         // don't do anything if there were no surfaces
11603         if (!numsurfacelist)
11604         {
11605                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11606                 return;
11607         }
11608         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11609
11610         // add to stats if desired
11611         if (r_speeds.integer && !skysurfaces && !depthonly)
11612         {
11613                 r_refdef.stats.world_surfaces += numsurfacelist;
11614                 for (j = 0;j < numsurfacelist;j++)
11615                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11616         }
11617
11618         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11619 }
11620
11621 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11622 {
11623         int i, j, endj, flagsmask;
11624         dp_model_t *model = ent->model;
11625         msurface_t *surfaces;
11626         unsigned char *update;
11627         int numsurfacelist = 0;
11628         if (model == NULL)
11629                 return;
11630
11631         if (r_maxsurfacelist < model->num_surfaces)
11632         {
11633                 r_maxsurfacelist = model->num_surfaces;
11634                 if (r_surfacelist)
11635                         Mem_Free((msurface_t **)r_surfacelist);
11636                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11637         }
11638
11639         // if the model is static it doesn't matter what value we give for
11640         // wantnormals and wanttangents, so this logic uses only rules applicable
11641         // to a model, knowing that they are meaningless otherwise
11642         if (ent == r_refdef.scene.worldentity)
11643                 RSurf_ActiveWorldEntity();
11644         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11645                 RSurf_ActiveModelEntity(ent, false, false, false);
11646         else if (prepass)
11647                 RSurf_ActiveModelEntity(ent, true, true, true);
11648         else if (depthonly)
11649         {
11650                 switch (vid.renderpath)
11651                 {
11652                 case RENDERPATH_GL20:
11653                 case RENDERPATH_D3D9:
11654                 case RENDERPATH_D3D10:
11655                 case RENDERPATH_D3D11:
11656                 case RENDERPATH_SOFT:
11657                 case RENDERPATH_GLES2:
11658                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11659                         break;
11660                 case RENDERPATH_GL11:
11661                 case RENDERPATH_GL13:
11662                 case RENDERPATH_GLES1:
11663                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11664                         break;
11665                 }
11666         }
11667         else
11668         {
11669                 switch (vid.renderpath)
11670                 {
11671                 case RENDERPATH_GL20:
11672                 case RENDERPATH_D3D9:
11673                 case RENDERPATH_D3D10:
11674                 case RENDERPATH_D3D11:
11675                 case RENDERPATH_SOFT:
11676                 case RENDERPATH_GLES2:
11677                         RSurf_ActiveModelEntity(ent, true, true, false);
11678                         break;
11679                 case RENDERPATH_GL11:
11680                 case RENDERPATH_GL13:
11681                 case RENDERPATH_GLES1:
11682                         RSurf_ActiveModelEntity(ent, true, false, false);
11683                         break;
11684                 }
11685         }
11686
11687         surfaces = model->data_surfaces;
11688         update = model->brushq1.lightmapupdateflags;
11689
11690         // update light styles
11691         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11692         {
11693                 model_brush_lightstyleinfo_t *style;
11694                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11695                 {
11696                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11697                         {
11698                                 int *list = style->surfacelist;
11699                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11700                                 for (j = 0;j < style->numsurfaces;j++)
11701                                         update[list[j]] = true;
11702                         }
11703                 }
11704         }
11705
11706         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11707
11708         if (debug)
11709         {
11710                 R_DrawDebugModel();
11711                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11712                 return;
11713         }
11714
11715         rsurface.lightmaptexture = NULL;
11716         rsurface.deluxemaptexture = NULL;
11717         rsurface.uselightmaptexture = false;
11718         rsurface.texture = NULL;
11719         rsurface.rtlight = NULL;
11720         numsurfacelist = 0;
11721         // add visible surfaces to draw list
11722         for (i = 0;i < model->nummodelsurfaces;i++)
11723                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11724         // don't do anything if there were no surfaces
11725         if (!numsurfacelist)
11726         {
11727                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11728                 return;
11729         }
11730         // update lightmaps if needed
11731         if (update)
11732         {
11733                 int updated = 0;
11734                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11735                 {
11736                         if (update[j])
11737                         {
11738                                 updated++;
11739                                 R_BuildLightMap(ent, surfaces + j);
11740                         }
11741                 }
11742         }
11743         if (update)
11744                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11745                         if (update[j])
11746                                 R_BuildLightMap(ent, surfaces + j);
11747         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11748
11749         // add to stats if desired
11750         if (r_speeds.integer && !skysurfaces && !depthonly)
11751         {
11752                 r_refdef.stats.entities_surfaces += numsurfacelist;
11753                 for (j = 0;j < numsurfacelist;j++)
11754                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11755         }
11756
11757         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11758 }
11759
11760 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11761 {
11762         static texture_t texture;
11763         static msurface_t surface;
11764         const msurface_t *surfacelist = &surface;
11765
11766         // fake enough texture and surface state to render this geometry
11767
11768         texture.update_lastrenderframe = -1; // regenerate this texture
11769         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11770         texture.currentskinframe = skinframe;
11771         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11772         texture.offsetmapping = OFFSETMAPPING_OFF;
11773         texture.offsetscale = 1;
11774         texture.specularscalemod = 1;
11775         texture.specularpowermod = 1;
11776
11777         surface.texture = &texture;
11778         surface.num_triangles = numtriangles;
11779         surface.num_firsttriangle = firsttriangle;
11780         surface.num_vertices = numvertices;
11781         surface.num_firstvertex = firstvertex;
11782
11783         // now render it
11784         rsurface.texture = R_GetCurrentTexture(surface.texture);
11785         rsurface.lightmaptexture = NULL;
11786         rsurface.deluxemaptexture = NULL;
11787         rsurface.uselightmaptexture = false;
11788         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11789 }
11790
11791 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)
11792 {
11793         static msurface_t surface;
11794         const msurface_t *surfacelist = &surface;
11795
11796         // fake enough texture and surface state to render this geometry
11797         surface.texture = texture;
11798         surface.num_triangles = numtriangles;
11799         surface.num_firsttriangle = firsttriangle;
11800         surface.num_vertices = numvertices;
11801         surface.num_firstvertex = firstvertex;
11802
11803         // now render it
11804         rsurface.texture = R_GetCurrentTexture(surface.texture);
11805         rsurface.lightmaptexture = NULL;
11806         rsurface.deluxemaptexture = NULL;
11807         rsurface.uselightmaptexture = false;
11808         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11809 }