]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix a pile of issues with calling conventions on GLES2 platforms by
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
104
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
108
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
122 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
131
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
140
141 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
142 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
143
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147
148 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
149 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
153 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
154 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156
157 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
169 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
173
174 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
206
207 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
208
209 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
210
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
214
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
217
218 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
219
220 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
221
222 extern cvar_t v_glslgamma;
223 extern cvar_t v_glslgamma_2d;
224
225 extern qboolean v_flipped_state;
226
227 static struct r_bloomstate_s
228 {
229         qboolean enabled;
230         qboolean hdr;
231
232         int bloomwidth, bloomheight;
233
234         textype_t texturetype;
235         int viewfbo; // used to check if r_viewfbo cvar has changed
236
237         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
238         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
239         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
240
241         int screentexturewidth, screentextureheight;
242         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
243
244         int bloomtexturewidth, bloomtextureheight;
245         rtexture_t *texture_bloom;
246
247         // arrays for rendering the screen passes
248         float screentexcoord2f[8];
249         float bloomtexcoord2f[8];
250         float offsettexcoord2f[8];
251
252         r_viewport_t viewport;
253 }
254 r_bloomstate;
255
256 r_waterstate_t r_waterstate;
257
258 /// shadow volume bsp struct with automatically growing nodes buffer
259 svbsp_t r_svbsp;
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 128; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstring =
617 #include "shader_glsl.h"
618 ;
619
620 const char *builtinhlslshaderstring =
621 #include "shader_hlsl.h"
622 ;
623
624 char *glslshaderstring = NULL;
625 char *hlslshaderstring = NULL;
626
627 //=======================================================================================================================================================
628
629 typedef struct shaderpermutationinfo_s
630 {
631         const char *pretext;
632         const char *name;
633 }
634 shaderpermutationinfo_t;
635
636 typedef struct shadermodeinfo_s
637 {
638         const char *vertexfilename;
639         const char *geometryfilename;
640         const char *fragmentfilename;
641         const char *pretext;
642         const char *name;
643 }
644 shadermodeinfo_t;
645
646 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
647 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
648 {
649         {"#define USEDIFFUSE\n", " diffuse"},
650         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
651         {"#define USEVIEWTINT\n", " viewtint"},
652         {"#define USECOLORMAPPING\n", " colormapping"},
653         {"#define USESATURATION\n", " saturation"},
654         {"#define USEFOGINSIDE\n", " foginside"},
655         {"#define USEFOGOUTSIDE\n", " fogoutside"},
656         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
657         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
658         {"#define USEGAMMARAMPS\n", " gammaramps"},
659         {"#define USECUBEFILTER\n", " cubefilter"},
660         {"#define USEGLOW\n", " glow"},
661         {"#define USEBLOOM\n", " bloom"},
662         {"#define USESPECULAR\n", " specular"},
663         {"#define USEPOSTPROCESSING\n", " postprocessing"},
664         {"#define USEREFLECTION\n", " reflection"},
665         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
666         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
667         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
668         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
669         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
670         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
671         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
672         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
673         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
674         {"#define USEALPHAKILL\n", " alphakill"},
675         {"#define USEREFLECTCUBE\n", " reflectcube"},
676         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
677         {"#define USEBOUNCEGRID\n", " bouncegrid"},
678         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
679         {"#define USETRIPPY\n", " trippy"},
680 };
681
682 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
683 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
684 {
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
703 };
704
705 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
706 {
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
716         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
717         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
725 };
726
727 struct r_glsl_permutation_s;
728 typedef struct r_glsl_permutation_s
729 {
730         /// hash lookup data
731         struct r_glsl_permutation_s *hashnext;
732         unsigned int mode;
733         unsigned int permutation;
734
735         /// indicates if we have tried compiling this permutation already
736         qboolean compiled;
737         /// 0 if compilation failed
738         int program;
739         // texture units assigned to each detected uniform
740         int tex_Texture_First;
741         int tex_Texture_Second;
742         int tex_Texture_GammaRamps;
743         int tex_Texture_Normal;
744         int tex_Texture_Color;
745         int tex_Texture_Gloss;
746         int tex_Texture_Glow;
747         int tex_Texture_SecondaryNormal;
748         int tex_Texture_SecondaryColor;
749         int tex_Texture_SecondaryGloss;
750         int tex_Texture_SecondaryGlow;
751         int tex_Texture_Pants;
752         int tex_Texture_Shirt;
753         int tex_Texture_FogHeightTexture;
754         int tex_Texture_FogMask;
755         int tex_Texture_Lightmap;
756         int tex_Texture_Deluxemap;
757         int tex_Texture_Attenuation;
758         int tex_Texture_Cube;
759         int tex_Texture_Refraction;
760         int tex_Texture_Reflection;
761         int tex_Texture_ShadowMap2D;
762         int tex_Texture_CubeProjection;
763         int tex_Texture_ScreenDepth;
764         int tex_Texture_ScreenNormalMap;
765         int tex_Texture_ScreenDiffuse;
766         int tex_Texture_ScreenSpecular;
767         int tex_Texture_ReflectMask;
768         int tex_Texture_ReflectCube;
769         int tex_Texture_BounceGrid;
770         /// locations of detected uniforms in program object, or -1 if not found
771         int loc_Texture_First;
772         int loc_Texture_Second;
773         int loc_Texture_GammaRamps;
774         int loc_Texture_Normal;
775         int loc_Texture_Color;
776         int loc_Texture_Gloss;
777         int loc_Texture_Glow;
778         int loc_Texture_SecondaryNormal;
779         int loc_Texture_SecondaryColor;
780         int loc_Texture_SecondaryGloss;
781         int loc_Texture_SecondaryGlow;
782         int loc_Texture_Pants;
783         int loc_Texture_Shirt;
784         int loc_Texture_FogHeightTexture;
785         int loc_Texture_FogMask;
786         int loc_Texture_Lightmap;
787         int loc_Texture_Deluxemap;
788         int loc_Texture_Attenuation;
789         int loc_Texture_Cube;
790         int loc_Texture_Refraction;
791         int loc_Texture_Reflection;
792         int loc_Texture_ShadowMap2D;
793         int loc_Texture_CubeProjection;
794         int loc_Texture_ScreenDepth;
795         int loc_Texture_ScreenNormalMap;
796         int loc_Texture_ScreenDiffuse;
797         int loc_Texture_ScreenSpecular;
798         int loc_Texture_ReflectMask;
799         int loc_Texture_ReflectCube;
800         int loc_Texture_BounceGrid;
801         int loc_Alpha;
802         int loc_BloomBlur_Parameters;
803         int loc_ClientTime;
804         int loc_Color_Ambient;
805         int loc_Color_Diffuse;
806         int loc_Color_Specular;
807         int loc_Color_Glow;
808         int loc_Color_Pants;
809         int loc_Color_Shirt;
810         int loc_DeferredColor_Ambient;
811         int loc_DeferredColor_Diffuse;
812         int loc_DeferredColor_Specular;
813         int loc_DeferredMod_Diffuse;
814         int loc_DeferredMod_Specular;
815         int loc_DistortScaleRefractReflect;
816         int loc_EyePosition;
817         int loc_FogColor;
818         int loc_FogHeightFade;
819         int loc_FogPlane;
820         int loc_FogPlaneViewDist;
821         int loc_FogRangeRecip;
822         int loc_LightColor;
823         int loc_LightDir;
824         int loc_LightPosition;
825         int loc_OffsetMapping_ScaleSteps;
826         int loc_PixelSize;
827         int loc_ReflectColor;
828         int loc_ReflectFactor;
829         int loc_ReflectOffset;
830         int loc_RefractColor;
831         int loc_Saturation;
832         int loc_ScreenCenterRefractReflect;
833         int loc_ScreenScaleRefractReflect;
834         int loc_ScreenToDepth;
835         int loc_ShadowMap_Parameters;
836         int loc_ShadowMap_TextureScale;
837         int loc_SpecularPower;
838         int loc_UserVec1;
839         int loc_UserVec2;
840         int loc_UserVec3;
841         int loc_UserVec4;
842         int loc_ViewTintColor;
843         int loc_ViewToLight;
844         int loc_ModelToLight;
845         int loc_TexMatrix;
846         int loc_BackgroundTexMatrix;
847         int loc_ModelViewProjectionMatrix;
848         int loc_ModelViewMatrix;
849         int loc_PixelToScreenTexCoord;
850         int loc_ModelToReflectCube;
851         int loc_ShadowMapMatrix;
852         int loc_BloomColorSubtract;
853         int loc_NormalmapScrollBlend;
854         int loc_BounceGridMatrix;
855         int loc_BounceGridIntensity;
856 }
857 r_glsl_permutation_t;
858
859 #define SHADERPERMUTATION_HASHSIZE 256
860
861
862 // non-degradable "lightweight" shader parameters to keep the permutations simpler
863 // these can NOT degrade! only use for simple stuff
864 enum
865 {
866         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
867         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
868         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
869         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
872         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
873 };
874 #define SHADERSTATICPARMS_COUNT 7
875
876 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
877 static int shaderstaticparms_count = 0;
878
879 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
880 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
881 qboolean R_CompileShader_CheckStaticParms(void)
882 {
883         static int r_compileshader_staticparms_save[1];
884         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
885         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
886
887         // detect all
888         if (r_glsl_saturation_redcompensate.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
890         if (r_glsl_vertextextureblend_usebothalphas.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
892         if (r_shadow_glossexact.integer)
893                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
894         if (r_glsl_postprocess.integer)
895         {
896                 if (r_glsl_postprocess_uservec1_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
898                 if (r_glsl_postprocess_uservec2_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
900                 if (r_glsl_postprocess_uservec3_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
902                 if (r_glsl_postprocess_uservec4_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
904         }
905         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
906 }
907
908 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
909         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
910                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
911         else \
912                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
913 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
914 {
915         shaderstaticparms_count = 0;
916
917         // emit all
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
925 }
926
927 /// information about each possible shader permutation
928 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
929 /// currently selected permutation
930 r_glsl_permutation_t *r_glsl_permutation;
931 /// storage for permutations linked in the hash table
932 memexpandablearray_t r_glsl_permutationarray;
933
934 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 {
936         //unsigned int hashdepth = 0;
937         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
938         r_glsl_permutation_t *p;
939         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940         {
941                 if (p->mode == mode && p->permutation == permutation)
942                 {
943                         //if (hashdepth > 10)
944                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945                         return p;
946                 }
947                 //hashdepth++;
948         }
949         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950         p->mode = mode;
951         p->permutation = permutation;
952         p->hashnext = r_glsl_permutationhash[mode][hashindex];
953         r_glsl_permutationhash[mode][hashindex] = p;
954         //if (hashdepth > 10)
955         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956         return p;
957 }
958
959 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 {
961         char *shaderstring;
962         if (!filename || !filename[0])
963                 return NULL;
964         if (!strcmp(filename, "glsl/default.glsl"))
965         {
966                 if (!glslshaderstring)
967                 {
968                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969                         if (glslshaderstring)
970                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
971                         else
972                                 glslshaderstring = (char *)builtinshaderstring;
973                 }
974                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
975                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976                 return shaderstring;
977         }
978         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979         if (shaderstring)
980         {
981                 if (printfromdisknotice)
982                         Con_DPrintf("from disk %s... ", filename);
983                 return shaderstring;
984         }
985         return shaderstring;
986 }
987
988 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 {
990         int i;
991         int sampler;
992         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
993         char *vertexstring, *geometrystring, *fragmentstring;
994         char permutationname[256];
995         int vertstrings_count = 0;
996         int geomstrings_count = 0;
997         int fragstrings_count = 0;
998         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
999         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001
1002         if (p->compiled)
1003                 return;
1004         p->compiled = true;
1005         p->program = 0;
1006
1007         permutationname[0] = 0;
1008         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1009         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1010         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011
1012         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013
1014         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1015         if(vid.support.gl20shaders130)
1016         {
1017                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1018                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1019                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1020                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1021                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1022                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023         }
1024
1025         // the first pretext is which type of shader to compile as
1026         // (later these will all be bound together as a program object)
1027         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1028         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1029         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030
1031         // the second pretext is the mode (for example a light source)
1032         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1033         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1034         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1035         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036
1037         // now add all the permutation pretexts
1038         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039         {
1040                 if (permutation & (1<<i))
1041                 {
1042                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046                 }
1047                 else
1048                 {
1049                         // keep line numbers correct
1050                         vertstrings_list[vertstrings_count++] = "\n";
1051                         geomstrings_list[geomstrings_count++] = "\n";
1052                         fragstrings_list[fragstrings_count++] = "\n";
1053                 }
1054         }
1055
1056         // add static parms
1057         R_CompileShader_AddStaticParms(mode, permutation);
1058         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         vertstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         geomstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         fragstrings_count += shaderstaticparms_count;
1064
1065         // now append the shader text itself
1066         vertstrings_list[vertstrings_count++] = vertexstring;
1067         geomstrings_list[geomstrings_count++] = geometrystring;
1068         fragstrings_list[fragstrings_count++] = fragmentstring;
1069
1070         // if any sources were NULL, clear the respective list
1071         if (!vertexstring)
1072                 vertstrings_count = 0;
1073         if (!geometrystring)
1074                 geomstrings_count = 0;
1075         if (!fragmentstring)
1076                 fragstrings_count = 0;
1077
1078         // compile the shader program
1079         if (vertstrings_count + geomstrings_count + fragstrings_count)
1080                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081         if (p->program)
1082         {
1083                 CHECKGLERROR
1084                 qglUseProgram(p->program);CHECKGLERROR
1085                 // look up all the uniform variable names we care about, so we don't
1086                 // have to look them up every time we set them
1087
1088                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1089                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1090                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1091                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1092                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1093                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1094                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1095                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1096                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1097                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1098                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1099                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1100                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1101                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1102                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1103                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1104                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1105                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1106                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1107                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1108                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1109                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1110                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1111                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1112                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1113                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1114                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1115                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1116                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1117                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1118                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1119                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1120                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1121                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1122                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1123                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1124                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1125                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1126                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1127                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1128                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1129                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1130                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1131                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1132                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1133                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1134                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1135                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1136                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1137                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1138                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1139                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1140                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1141                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1142                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1143                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1144                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1145                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1146                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1147                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1148                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1149                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1150                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1151                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1152                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1153                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1154                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1155                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1156                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1157                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1158                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1159                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1160                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1161                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1162                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1163                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1164                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1165                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1166                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1167                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1168                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1169                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1170                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1171                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1172                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1173                 // initialize the samplers to refer to the texture units we use
1174                 p->tex_Texture_First = -1;
1175                 p->tex_Texture_Second = -1;
1176                 p->tex_Texture_GammaRamps = -1;
1177                 p->tex_Texture_Normal = -1;
1178                 p->tex_Texture_Color = -1;
1179                 p->tex_Texture_Gloss = -1;
1180                 p->tex_Texture_Glow = -1;
1181                 p->tex_Texture_SecondaryNormal = -1;
1182                 p->tex_Texture_SecondaryColor = -1;
1183                 p->tex_Texture_SecondaryGloss = -1;
1184                 p->tex_Texture_SecondaryGlow = -1;
1185                 p->tex_Texture_Pants = -1;
1186                 p->tex_Texture_Shirt = -1;
1187                 p->tex_Texture_FogHeightTexture = -1;
1188                 p->tex_Texture_FogMask = -1;
1189                 p->tex_Texture_Lightmap = -1;
1190                 p->tex_Texture_Deluxemap = -1;
1191                 p->tex_Texture_Attenuation = -1;
1192                 p->tex_Texture_Cube = -1;
1193                 p->tex_Texture_Refraction = -1;
1194                 p->tex_Texture_Reflection = -1;
1195                 p->tex_Texture_ShadowMap2D = -1;
1196                 p->tex_Texture_CubeProjection = -1;
1197                 p->tex_Texture_ScreenDepth = -1;
1198                 p->tex_Texture_ScreenNormalMap = -1;
1199                 p->tex_Texture_ScreenDiffuse = -1;
1200                 p->tex_Texture_ScreenSpecular = -1;
1201                 p->tex_Texture_ReflectMask = -1;
1202                 p->tex_Texture_ReflectCube = -1;
1203                 p->tex_Texture_BounceGrid = -1;
1204                 sampler = 0;
1205                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1206                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1207                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1208                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1209                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1210                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1211                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1216                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1217                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1218                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1219                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1220                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1221                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1222                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1223                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1224                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1225                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1226                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1227                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1233                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1234                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1235                 CHECKGLERROR
1236                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1237         }
1238         else
1239                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1240
1241         // free the strings
1242         if (vertexstring)
1243                 Mem_Free(vertexstring);
1244         if (geometrystring)
1245                 Mem_Free(geometrystring);
1246         if (fragmentstring)
1247                 Mem_Free(fragmentstring);
1248 }
1249
1250 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1251 {
1252         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1253         if (r_glsl_permutation != perm)
1254         {
1255                 r_glsl_permutation = perm;
1256                 if (!r_glsl_permutation->program)
1257                 {
1258                         if (!r_glsl_permutation->compiled)
1259                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1260                         if (!r_glsl_permutation->program)
1261                         {
1262                                 // remove features until we find a valid permutation
1263                                 int i;
1264                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1265                                 {
1266                                         // reduce i more quickly whenever it would not remove any bits
1267                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1268                                         if (!(permutation & j))
1269                                                 continue;
1270                                         permutation -= j;
1271                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1272                                         if (!r_glsl_permutation->compiled)
1273                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1274                                         if (r_glsl_permutation->program)
1275                                                 break;
1276                                 }
1277                                 if (i >= SHADERPERMUTATION_COUNT)
1278                                 {
1279                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         qglUseProgram(0);CHECKGLERROR
1282                                         return; // no bit left to clear, entire mode is broken
1283                                 }
1284                         }
1285                 }
1286                 CHECKGLERROR
1287                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1288         }
1289         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1290         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1291         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1292 }
1293
1294 #ifdef SUPPORTD3D
1295
1296 #ifdef SUPPORTD3D
1297 #include <d3d9.h>
1298 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1299 extern D3DCAPS9 vid_d3d9caps;
1300 #endif
1301
1302 struct r_hlsl_permutation_s;
1303 typedef struct r_hlsl_permutation_s
1304 {
1305         /// hash lookup data
1306         struct r_hlsl_permutation_s *hashnext;
1307         unsigned int mode;
1308         unsigned int permutation;
1309
1310         /// indicates if we have tried compiling this permutation already
1311         qboolean compiled;
1312         /// NULL if compilation failed
1313         IDirect3DVertexShader9 *vertexshader;
1314         IDirect3DPixelShader9 *pixelshader;
1315 }
1316 r_hlsl_permutation_t;
1317
1318 typedef enum D3DVSREGISTER_e
1319 {
1320         D3DVSREGISTER_TexMatrix = 0, // float4x4
1321         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1322         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1323         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1324         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1325         D3DVSREGISTER_ModelToLight = 20, // float4x4
1326         D3DVSREGISTER_EyePosition = 24,
1327         D3DVSREGISTER_FogPlane = 25,
1328         D3DVSREGISTER_LightDir = 26,
1329         D3DVSREGISTER_LightPosition = 27,
1330 }
1331 D3DVSREGISTER_t;
1332
1333 typedef enum D3DPSREGISTER_e
1334 {
1335         D3DPSREGISTER_Alpha = 0,
1336         D3DPSREGISTER_BloomBlur_Parameters = 1,
1337         D3DPSREGISTER_ClientTime = 2,
1338         D3DPSREGISTER_Color_Ambient = 3,
1339         D3DPSREGISTER_Color_Diffuse = 4,
1340         D3DPSREGISTER_Color_Specular = 5,
1341         D3DPSREGISTER_Color_Glow = 6,
1342         D3DPSREGISTER_Color_Pants = 7,
1343         D3DPSREGISTER_Color_Shirt = 8,
1344         D3DPSREGISTER_DeferredColor_Ambient = 9,
1345         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1346         D3DPSREGISTER_DeferredColor_Specular = 11,
1347         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1348         D3DPSREGISTER_DeferredMod_Specular = 13,
1349         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1350         D3DPSREGISTER_EyePosition = 15, // unused
1351         D3DPSREGISTER_FogColor = 16,
1352         D3DPSREGISTER_FogHeightFade = 17,
1353         D3DPSREGISTER_FogPlane = 18,
1354         D3DPSREGISTER_FogPlaneViewDist = 19,
1355         D3DPSREGISTER_FogRangeRecip = 20,
1356         D3DPSREGISTER_LightColor = 21,
1357         D3DPSREGISTER_LightDir = 22, // unused
1358         D3DPSREGISTER_LightPosition = 23,
1359         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1360         D3DPSREGISTER_PixelSize = 25,
1361         D3DPSREGISTER_ReflectColor = 26,
1362         D3DPSREGISTER_ReflectFactor = 27,
1363         D3DPSREGISTER_ReflectOffset = 28,
1364         D3DPSREGISTER_RefractColor = 29,
1365         D3DPSREGISTER_Saturation = 30,
1366         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1367         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1368         D3DPSREGISTER_ScreenToDepth = 33,
1369         D3DPSREGISTER_ShadowMap_Parameters = 34,
1370         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1371         D3DPSREGISTER_SpecularPower = 36,
1372         D3DPSREGISTER_UserVec1 = 37,
1373         D3DPSREGISTER_UserVec2 = 38,
1374         D3DPSREGISTER_UserVec3 = 39,
1375         D3DPSREGISTER_UserVec4 = 40,
1376         D3DPSREGISTER_ViewTintColor = 41,
1377         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1378         D3DPSREGISTER_BloomColorSubtract = 43,
1379         D3DPSREGISTER_ViewToLight = 44, // float4x4
1380         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1381         D3DPSREGISTER_NormalmapScrollBlend = 52,
1382         // next at 53
1383 }
1384 D3DPSREGISTER_t;
1385
1386 /// information about each possible shader permutation
1387 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1388 /// currently selected permutation
1389 r_hlsl_permutation_t *r_hlsl_permutation;
1390 /// storage for permutations linked in the hash table
1391 memexpandablearray_t r_hlsl_permutationarray;
1392
1393 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1394 {
1395         //unsigned int hashdepth = 0;
1396         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1397         r_hlsl_permutation_t *p;
1398         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1399         {
1400                 if (p->mode == mode && p->permutation == permutation)
1401                 {
1402                         //if (hashdepth > 10)
1403                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1404                         return p;
1405                 }
1406                 //hashdepth++;
1407         }
1408         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1409         p->mode = mode;
1410         p->permutation = permutation;
1411         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1412         r_hlsl_permutationhash[mode][hashindex] = p;
1413         //if (hashdepth > 10)
1414         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415         return p;
1416 }
1417
1418 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1419 {
1420         char *shaderstring;
1421         if (!filename || !filename[0])
1422                 return NULL;
1423         if (!strcmp(filename, "hlsl/default.hlsl"))
1424         {
1425                 if (!hlslshaderstring)
1426                 {
1427                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428                         if (hlslshaderstring)
1429                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1430                         else
1431                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1432                 }
1433                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1434                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1435                 return shaderstring;
1436         }
1437         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438         if (shaderstring)
1439         {
1440                 if (printfromdisknotice)
1441                         Con_DPrintf("from disk %s... ", filename);
1442                 return shaderstring;
1443         }
1444         return shaderstring;
1445 }
1446
1447 #include <d3dx9.h>
1448 //#include <d3dx9shader.h>
1449 //#include <d3dx9mesh.h>
1450
1451 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1452 {
1453         DWORD *vsbin = NULL;
1454         DWORD *psbin = NULL;
1455         fs_offset_t vsbinsize;
1456         fs_offset_t psbinsize;
1457 //      IDirect3DVertexShader9 *vs = NULL;
1458 //      IDirect3DPixelShader9 *ps = NULL;
1459         ID3DXBuffer *vslog = NULL;
1460         ID3DXBuffer *vsbuffer = NULL;
1461         ID3DXConstantTable *vsconstanttable = NULL;
1462         ID3DXBuffer *pslog = NULL;
1463         ID3DXBuffer *psbuffer = NULL;
1464         ID3DXConstantTable *psconstanttable = NULL;
1465         int vsresult = 0;
1466         int psresult = 0;
1467         char temp[MAX_INPUTLINE];
1468         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1469         qboolean debugshader = gl_paranoid.integer != 0;
1470         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (!debugshader)
1473         {
1474                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1475                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1476         }
1477         if ((!vsbin && vertstring) || (!psbin && fragstring))
1478         {
1479                 const char* dllnames_d3dx9 [] =
1480                 {
1481                         "d3dx9_43.dll",
1482                         "d3dx9_42.dll",
1483                         "d3dx9_41.dll",
1484                         "d3dx9_40.dll",
1485                         "d3dx9_39.dll",
1486                         "d3dx9_38.dll",
1487                         "d3dx9_37.dll",
1488                         "d3dx9_36.dll",
1489                         "d3dx9_35.dll",
1490                         "d3dx9_34.dll",
1491                         "d3dx9_33.dll",
1492                         "d3dx9_32.dll",
1493                         "d3dx9_31.dll",
1494                         "d3dx9_30.dll",
1495                         "d3dx9_29.dll",
1496                         "d3dx9_28.dll",
1497                         "d3dx9_27.dll",
1498                         "d3dx9_26.dll",
1499                         "d3dx9_25.dll",
1500                         "d3dx9_24.dll",
1501                         NULL
1502                 };
1503                 dllhandle_t d3dx9_dll = NULL;
1504                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1505                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1506                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 dllfunction_t d3dx9_dllfuncs[] =
1508                 {
1509                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1510                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1511                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1512                         {NULL, NULL}
1513                 };
1514                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1515                 {
1516                         DWORD shaderflags = 0;
1517                         if (debugshader)
1518                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1519                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1520                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1521                         if (vertstring && vertstring[0])
1522                         {
1523                                 if (debugshader)
1524                                 {
1525 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1526 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1527                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1528                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1529                                 }
1530                                 else
1531                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1532                                 if (vsbuffer)
1533                                 {
1534                                         vsbinsize = vsbuffer->GetBufferSize();
1535                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1536                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1537                                         vsbuffer->Release();
1538                                 }
1539                                 if (vslog)
1540                                 {
1541                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1542                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1543                                         vslog->Release();
1544                                 }
1545                         }
1546                         if (fragstring && fragstring[0])
1547                         {
1548                                 if (debugshader)
1549                                 {
1550 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1551 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1552                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1553                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1554                                 }
1555                                 else
1556                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1557                                 if (psbuffer)
1558                                 {
1559                                         psbinsize = psbuffer->GetBufferSize();
1560                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1561                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1562                                         psbuffer->Release();
1563                                 }
1564                                 if (pslog)
1565                                 {
1566                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1567                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1568                                         pslog->Release();
1569                                 }
1570                         }
1571                         Sys_UnloadLibrary(&d3dx9_dll);
1572                 }
1573                 else
1574                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1575         }
1576         if (vsbin && psbin)
1577         {
1578                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1579                 if (FAILED(vsresult))
1580                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1581                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1582                 if (FAILED(psresult))
1583                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1584         }
1585         // free the shader data
1586         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1587         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1588 }
1589
1590 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1591 {
1592         int i;
1593         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1594         int vertstring_length = 0;
1595         int geomstring_length = 0;
1596         int fragstring_length = 0;
1597         char *t;
1598         char *vertexstring, *geometrystring, *fragmentstring;
1599         char *vertstring, *geomstring, *fragstring;
1600         char permutationname[256];
1601         char cachename[256];
1602         int vertstrings_count = 0;
1603         int geomstrings_count = 0;
1604         int fragstrings_count = 0;
1605         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1606         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608
1609         if (p->compiled)
1610                 return;
1611         p->compiled = true;
1612         p->vertexshader = NULL;
1613         p->pixelshader = NULL;
1614
1615         permutationname[0] = 0;
1616         cachename[0] = 0;
1617         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1618         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1619         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1620
1621         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1622         strlcat(cachename, "hlsl/", sizeof(cachename));
1623
1624         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1625         vertstrings_count = 0;
1626         geomstrings_count = 0;
1627         fragstrings_count = 0;
1628         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1629         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1630         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1631
1632         // the first pretext is which type of shader to compile as
1633         // (later these will all be bound together as a program object)
1634         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1635         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1636         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1637
1638         // the second pretext is the mode (for example a light source)
1639         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1640         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1641         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1642         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1643         strlcat(cachename, modeinfo->name, sizeof(cachename));
1644
1645         // now add all the permutation pretexts
1646         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1647         {
1648                 if (permutation & (1<<i))
1649                 {
1650                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1651                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1654                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1655                 }
1656                 else
1657                 {
1658                         // keep line numbers correct
1659                         vertstrings_list[vertstrings_count++] = "\n";
1660                         geomstrings_list[geomstrings_count++] = "\n";
1661                         fragstrings_list[fragstrings_count++] = "\n";
1662                 }
1663         }
1664
1665         // add static parms
1666         R_CompileShader_AddStaticParms(mode, permutation);
1667         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1668         vertstrings_count += shaderstaticparms_count;
1669         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         geomstrings_count += shaderstaticparms_count;
1671         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         fragstrings_count += shaderstaticparms_count;
1673
1674         // replace spaces in the cachename with _ characters
1675         for (i = 0;cachename[i];i++)
1676                 if (cachename[i] == ' ')
1677                         cachename[i] = '_';
1678
1679         // now append the shader text itself
1680         vertstrings_list[vertstrings_count++] = vertexstring;
1681         geomstrings_list[geomstrings_count++] = geometrystring;
1682         fragstrings_list[fragstrings_count++] = fragmentstring;
1683
1684         // if any sources were NULL, clear the respective list
1685         if (!vertexstring)
1686                 vertstrings_count = 0;
1687         if (!geometrystring)
1688                 geomstrings_count = 0;
1689         if (!fragmentstring)
1690                 fragstrings_count = 0;
1691
1692         vertstring_length = 0;
1693         for (i = 0;i < vertstrings_count;i++)
1694                 vertstring_length += strlen(vertstrings_list[i]);
1695         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1696         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1697                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1698
1699         geomstring_length = 0;
1700         for (i = 0;i < geomstrings_count;i++)
1701                 geomstring_length += strlen(geomstrings_list[i]);
1702         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1703         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1704                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1705
1706         fragstring_length = 0;
1707         for (i = 0;i < fragstrings_count;i++)
1708                 fragstring_length += strlen(fragstrings_list[i]);
1709         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1710         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1711                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1712
1713         // try to load the cached shader, or generate one
1714         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1715
1716         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1717                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1718         else
1719                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1720
1721         // free the strings
1722         if (vertstring)
1723                 Mem_Free(vertstring);
1724         if (geomstring)
1725                 Mem_Free(geomstring);
1726         if (fragstring)
1727                 Mem_Free(fragstring);
1728         if (vertexstring)
1729                 Mem_Free(vertexstring);
1730         if (geometrystring)
1731                 Mem_Free(geometrystring);
1732         if (fragmentstring)
1733                 Mem_Free(fragmentstring);
1734 }
1735
1736 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1737 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1738 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1740 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742
1743 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1744 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1745 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1746 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1747 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1748 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1749
1750 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1751 {
1752         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1753         if (r_hlsl_permutation != perm)
1754         {
1755                 r_hlsl_permutation = perm;
1756                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1757                 {
1758                         if (!r_hlsl_permutation->compiled)
1759                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1760                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1761                         {
1762                                 // remove features until we find a valid permutation
1763                                 int i;
1764                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1765                                 {
1766                                         // reduce i more quickly whenever it would not remove any bits
1767                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1768                                         if (!(permutation & j))
1769                                                 continue;
1770                                         permutation -= j;
1771                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1772                                         if (!r_hlsl_permutation->compiled)
1773                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1774                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1775                                                 break;
1776                                 }
1777                                 if (i >= SHADERPERMUTATION_COUNT)
1778                                 {
1779                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1780                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1781                                         return; // no bit left to clear, entire mode is broken
1782                                 }
1783                         }
1784                 }
1785                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1786                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1787         }
1788         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1790         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1791 }
1792 #endif
1793
1794 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1795 {
1796         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1797         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1799         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1800 }
1801
1802 void R_GLSL_Restart_f(void)
1803 {
1804         unsigned int i, limit;
1805         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1806                 Mem_Free(glslshaderstring);
1807         glslshaderstring = NULL;
1808         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1809                 Mem_Free(hlslshaderstring);
1810         hlslshaderstring = NULL;
1811         switch(vid.renderpath)
1812         {
1813         case RENDERPATH_D3D9:
1814 #ifdef SUPPORTD3D
1815                 {
1816                         r_hlsl_permutation_t *p;
1817                         r_hlsl_permutation = NULL;
1818                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1819                         for (i = 0;i < limit;i++)
1820                         {
1821                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1822                                 {
1823                                         if (p->vertexshader)
1824                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1825                                         if (p->pixelshader)
1826                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1827                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1828                                 }
1829                         }
1830                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1831                 }
1832 #endif
1833                 break;
1834         case RENDERPATH_D3D10:
1835                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1836                 break;
1837         case RENDERPATH_D3D11:
1838                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1839                 break;
1840         case RENDERPATH_GL20:
1841         case RENDERPATH_GLES2:
1842                 {
1843                         r_glsl_permutation_t *p;
1844                         r_glsl_permutation = NULL;
1845                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1846                         for (i = 0;i < limit;i++)
1847                         {
1848                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1849                                 {
1850                                         GL_Backend_FreeProgram(p->program);
1851                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1852                                 }
1853                         }
1854                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1855                 }
1856                 break;
1857         case RENDERPATH_GL11:
1858         case RENDERPATH_GL13:
1859         case RENDERPATH_GLES1:
1860                 break;
1861         case RENDERPATH_SOFT:
1862                 break;
1863         }
1864 }
1865
1866 void R_GLSL_DumpShader_f(void)
1867 {
1868         int i;
1869         qfile_t *file;
1870
1871         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1872         if (file)
1873         {
1874                 FS_Print(file, "/* The engine may define the following macros:\n");
1875                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1876                 for (i = 0;i < SHADERMODE_COUNT;i++)
1877                         FS_Print(file, glslshadermodeinfo[i].pretext);
1878                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1879                         FS_Print(file, shaderpermutationinfo[i].pretext);
1880                 FS_Print(file, "*/\n");
1881                 FS_Print(file, builtinshaderstring);
1882                 FS_Close(file);
1883                 Con_Printf("glsl/default.glsl written\n");
1884         }
1885         else
1886                 Con_Printf("failed to write to glsl/default.glsl\n");
1887
1888         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1889         if (file)
1890         {
1891                 FS_Print(file, "/* The engine may define the following macros:\n");
1892                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1893                 for (i = 0;i < SHADERMODE_COUNT;i++)
1894                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1895                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1896                         FS_Print(file, shaderpermutationinfo[i].pretext);
1897                 FS_Print(file, "*/\n");
1898                 FS_Print(file, builtinhlslshaderstring);
1899                 FS_Close(file);
1900                 Con_Printf("hlsl/default.hlsl written\n");
1901         }
1902         else
1903                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1904 }
1905
1906 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1907 {
1908         unsigned int permutation = 0;
1909         if (r_trippy.integer && !notrippy)
1910                 permutation |= SHADERPERMUTATION_TRIPPY;
1911         permutation |= SHADERPERMUTATION_VIEWTINT;
1912         if (first)
1913                 permutation |= SHADERPERMUTATION_DIFFUSE;
1914         if (second)
1915                 permutation |= SHADERPERMUTATION_SPECULAR;
1916         if (texturemode == GL_MODULATE)
1917                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1918         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1919                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1920         else if (texturemode == GL_ADD)
1921                 permutation |= SHADERPERMUTATION_GLOW;
1922         else if (texturemode == GL_DECAL)
1923                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1924         if (!second)
1925                 texturemode = GL_MODULATE;
1926         if (vid.allowalphatocoverage)
1927                 GL_AlphaToCoverage(false);
1928         switch (vid.renderpath)
1929         {
1930         case RENDERPATH_D3D9:
1931 #ifdef SUPPORTD3D
1932                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1933                 R_Mesh_TexBind(GL20TU_FIRST , first );
1934                 R_Mesh_TexBind(GL20TU_SECOND, second);
1935                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1936                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1937 #endif
1938                 break;
1939         case RENDERPATH_D3D10:
1940                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1941                 break;
1942         case RENDERPATH_D3D11:
1943                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1944                 break;
1945         case RENDERPATH_GL20:
1946         case RENDERPATH_GLES2:
1947                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1949                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1950                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952                 break;
1953         case RENDERPATH_GL13:
1954         case RENDERPATH_GLES1:
1955                 R_Mesh_TexBind(0, first );
1956                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1957                 R_Mesh_TexBind(1, second);
1958                 if (second)
1959                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1960                 break;
1961         case RENDERPATH_GL11:
1962                 R_Mesh_TexBind(0, first );
1963                 break;
1964         case RENDERPATH_SOFT:
1965                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1966                 R_Mesh_TexBind(GL20TU_FIRST , first );
1967                 R_Mesh_TexBind(GL20TU_SECOND, second);
1968                 break;
1969         }
1970 }
1971
1972 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1973 {
1974         unsigned int permutation = 0;
1975         if (r_trippy.integer && !notrippy)
1976                 permutation |= SHADERPERMUTATION_TRIPPY;
1977         if (vid.allowalphatocoverage)
1978                 GL_AlphaToCoverage(false);
1979         switch (vid.renderpath)
1980         {
1981         case RENDERPATH_D3D9:
1982 #ifdef SUPPORTD3D
1983                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1984 #endif
1985                 break;
1986         case RENDERPATH_D3D10:
1987                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1988                 break;
1989         case RENDERPATH_D3D11:
1990                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1991                 break;
1992         case RENDERPATH_GL20:
1993         case RENDERPATH_GLES2:
1994                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995                 break;
1996         case RENDERPATH_GL13:
1997         case RENDERPATH_GLES1:
1998                 R_Mesh_TexBind(0, 0);
1999                 R_Mesh_TexBind(1, 0);
2000                 break;
2001         case RENDERPATH_GL11:
2002                 R_Mesh_TexBind(0, 0);
2003                 break;
2004         case RENDERPATH_SOFT:
2005                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         }
2008 }
2009
2010 void R_SetupShader_ShowDepth(qboolean notrippy)
2011 {
2012         int permutation = 0;
2013         if (r_trippy.integer && !notrippy)
2014                 permutation |= SHADERPERMUTATION_TRIPPY;
2015         if (vid.allowalphatocoverage)
2016                 GL_AlphaToCoverage(false);
2017         switch (vid.renderpath)
2018         {
2019         case RENDERPATH_D3D9:
2020 #ifdef SUPPORTHLSL
2021                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2022 #endif
2023                 break;
2024         case RENDERPATH_D3D10:
2025                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2026                 break;
2027         case RENDERPATH_D3D11:
2028                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2029                 break;
2030         case RENDERPATH_GL20:
2031         case RENDERPATH_GLES2:
2032                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2033                 break;
2034         case RENDERPATH_GL13:
2035         case RENDERPATH_GLES1:
2036                 break;
2037         case RENDERPATH_GL11:
2038                 break;
2039         case RENDERPATH_SOFT:
2040                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2041                 break;
2042         }
2043 }
2044
2045 extern qboolean r_shadow_usingdeferredprepass;
2046 extern cvar_t r_shadow_deferred_8bitrange;
2047 extern rtexture_t *r_shadow_attenuationgradienttexture;
2048 extern rtexture_t *r_shadow_attenuation2dtexture;
2049 extern rtexture_t *r_shadow_attenuation3dtexture;
2050 extern qboolean r_shadow_usingshadowmap2d;
2051 extern qboolean r_shadow_usingshadowmaportho;
2052 extern float r_shadow_shadowmap_texturescale[2];
2053 extern float r_shadow_shadowmap_parameters[4];
2054 extern qboolean r_shadow_shadowmapvsdct;
2055 extern qboolean r_shadow_shadowmapsampler;
2056 extern int r_shadow_shadowmappcf;
2057 extern rtexture_t *r_shadow_shadowmap2dtexture;
2058 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2059 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2060 extern matrix4x4_t r_shadow_shadowmapmatrix;
2061 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2062 extern int r_shadow_prepass_width;
2063 extern int r_shadow_prepass_height;
2064 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2065 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2066 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2067 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2068 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2069
2070 #define BLENDFUNC_ALLOWS_COLORMOD      1
2071 #define BLENDFUNC_ALLOWS_FOG           2
2072 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2073 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2074 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2075 static int R_BlendFuncFlags(int src, int dst)
2076 {
2077         int r = 0;
2078
2079         // a blendfunc allows colormod if:
2080         // a) it can never keep the destination pixel invariant, or
2081         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2082         // this is to prevent unintended side effects from colormod
2083
2084         // a blendfunc allows fog if:
2085         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2086         // this is to prevent unintended side effects from fog
2087
2088         // these checks are the output of fogeval.pl
2089
2090         r |= BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2100         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2105         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112
2113         return r;
2114 }
2115
2116 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2117 {
2118         // select a permutation of the lighting shader appropriate to this
2119         // combination of texture, entity, light source, and fogging, only use the
2120         // minimum features necessary to avoid wasting rendering time in the
2121         // fragment shader on features that are not being used
2122         unsigned int permutation = 0;
2123         unsigned int mode = 0;
2124         int blendfuncflags;
2125         static float dummy_colormod[3] = {1, 1, 1};
2126         float *colormod = rsurface.colormod;
2127         float m16f[16];
2128         matrix4x4_t tempmatrix;
2129         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2130         if (r_trippy.integer && !notrippy)
2131                 permutation |= SHADERPERMUTATION_TRIPPY;
2132         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2133                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2134         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2135                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2136         if (rsurfacepass == RSURFPASS_BACKGROUND)
2137         {
2138                 // distorted background
2139                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2140                 {
2141                         mode = SHADERMODE_WATER;
2142                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2143                         {
2144                                 // this is the right thing to do for wateralpha
2145                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2147                         }
2148                         else
2149                         {
2150                                 // this is the right thing to do for entity alpha
2151                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                         }
2154                 }
2155                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2156                 {
2157                         mode = SHADERMODE_REFRACTION;
2158                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2159                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160                 }
2161                 else
2162                 {
2163                         mode = SHADERMODE_GENERIC;
2164                         permutation |= SHADERPERMUTATION_DIFFUSE;
2165                         GL_BlendFunc(GL_ONE, GL_ZERO);
2166                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167                 }
2168                 if (vid.allowalphatocoverage)
2169                         GL_AlphaToCoverage(false);
2170         }
2171         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2172         {
2173                 if (r_glsl_offsetmapping.integer)
2174                 {
2175                         switch(rsurface.texture->offsetmapping)
2176                         {
2177                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2178                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2179                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180                         case OFFSETMAPPING_OFF: break;
2181                         }
2182                 }
2183                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2184                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2185                 // normalmap (deferred prepass), may use alpha test on diffuse
2186                 mode = SHADERMODE_DEFERREDGEOMETRY;
2187                 GL_BlendFunc(GL_ONE, GL_ZERO);
2188                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2189                 if (vid.allowalphatocoverage)
2190                         GL_AlphaToCoverage(false);
2191         }
2192         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2193         {
2194                 if (r_glsl_offsetmapping.integer)
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // light source
2207                 mode = SHADERMODE_LIGHTSOURCE;
2208                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2209                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2210                 if (diffusescale > 0)
2211                         permutation |= SHADERPERMUTATION_DIFFUSE;
2212                 if (specularscale > 0)
2213                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2214                 if (r_refdef.fogenabled)
2215                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2216                 if (rsurface.texture->colormapping)
2217                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2218                 if (r_shadow_usingshadowmap2d)
2219                 {
2220                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2221                         if(r_shadow_shadowmapvsdct)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2223
2224                         if (r_shadow_shadowmapsampler)
2225                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2226                         if (r_shadow_shadowmappcf > 1)
2227                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2228                         else if (r_shadow_shadowmappcf)
2229                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2230                 }
2231                 if (rsurface.texture->reflectmasktexture)
2232                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2233                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2234                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2235                 if (vid.allowalphatocoverage)
2236                         GL_AlphaToCoverage(false);
2237         }
2238         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2239         {
2240                 if (r_glsl_offsetmapping.integer)
2241                 {
2242                         switch(rsurface.texture->offsetmapping)
2243                         {
2244                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2245                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2246                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247                         case OFFSETMAPPING_OFF: break;
2248                         }
2249                 }
2250                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2251                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2252                 // unshaded geometry (fullbright or ambient model lighting)
2253                 mode = SHADERMODE_FLATCOLOR;
2254                 ambientscale = diffusescale = specularscale = 0;
2255                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2256                         permutation |= SHADERPERMUTATION_GLOW;
2257                 if (r_refdef.fogenabled)
2258                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2259                 if (rsurface.texture->colormapping)
2260                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2261                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2262                 {
2263                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2264                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2265
2266                         if (r_shadow_shadowmapsampler)
2267                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2268                         if (r_shadow_shadowmappcf > 1)
2269                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2270                         else if (r_shadow_shadowmappcf)
2271                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2274                         permutation |= SHADERPERMUTATION_REFLECTION;
2275                 if (rsurface.texture->reflectmasktexture)
2276                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2277                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2278                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 // when using alphatocoverage, we don't need alphakill
2280                 if (vid.allowalphatocoverage)
2281                 {
2282                         if (r_transparent_alphatocoverage.integer)
2283                         {
2284                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2285                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2286                         }
2287                         else
2288                                 GL_AlphaToCoverage(false);
2289                 }
2290         }
2291         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2292         {
2293                 if (r_glsl_offsetmapping.integer)
2294                 {
2295                         switch(rsurface.texture->offsetmapping)
2296                         {
2297                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2298                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2299                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_OFF: break;
2301                         }
2302                 }
2303                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2304                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2305                 // directional model lighting
2306                 mode = SHADERMODE_LIGHTDIRECTION;
2307                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2308                         permutation |= SHADERPERMUTATION_GLOW;
2309                 permutation |= SHADERPERMUTATION_DIFFUSE;
2310                 if (specularscale > 0)
2311                         permutation |= SHADERPERMUTATION_SPECULAR;
2312                 if (r_refdef.fogenabled)
2313                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2314                 if (rsurface.texture->colormapping)
2315                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2316                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2317                 {
2318                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2319                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2320
2321                         if (r_shadow_shadowmapsampler)
2322                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2323                         if (r_shadow_shadowmappcf > 1)
2324                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2325                         else if (r_shadow_shadowmappcf)
2326                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2327                 }
2328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2329                         permutation |= SHADERPERMUTATION_REFLECTION;
2330                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2331                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2332                 if (rsurface.texture->reflectmasktexture)
2333                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2334                 if (r_shadow_bouncegridtexture)
2335                 {
2336                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2337                         if (r_shadow_bouncegriddirectional)
2338                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2339                 }
2340                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2341                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 // when using alphatocoverage, we don't need alphakill
2343                 if (vid.allowalphatocoverage)
2344                 {
2345                         if (r_transparent_alphatocoverage.integer)
2346                         {
2347                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2348                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2349                         }
2350                         else
2351                                 GL_AlphaToCoverage(false);
2352                 }
2353         }
2354         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2355         {
2356                 if (r_glsl_offsetmapping.integer)
2357                 {
2358                         switch(rsurface.texture->offsetmapping)
2359                         {
2360                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2361                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2362                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_OFF: break;
2364                         }
2365                 }
2366                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2367                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2368                 // ambient model lighting
2369                 mode = SHADERMODE_LIGHTDIRECTION;
2370                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2371                         permutation |= SHADERPERMUTATION_GLOW;
2372                 if (r_refdef.fogenabled)
2373                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2374                 if (rsurface.texture->colormapping)
2375                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2376                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2377                 {
2378                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2379                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2380
2381                         if (r_shadow_shadowmapsampler)
2382                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2383                         if (r_shadow_shadowmappcf > 1)
2384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2385                         else if (r_shadow_shadowmappcf)
2386                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2389                         permutation |= SHADERPERMUTATION_REFLECTION;
2390                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2391                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2392                 if (rsurface.texture->reflectmasktexture)
2393                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2394                 if (r_shadow_bouncegridtexture)
2395                 {
2396                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2397                         if (r_shadow_bouncegriddirectional)
2398                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2399                 }
2400                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2401                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402                 // when using alphatocoverage, we don't need alphakill
2403                 if (vid.allowalphatocoverage)
2404                 {
2405                         if (r_transparent_alphatocoverage.integer)
2406                         {
2407                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2408                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2409                         }
2410                         else
2411                                 GL_AlphaToCoverage(false);
2412                 }
2413         }
2414         else
2415         {
2416                 if (r_glsl_offsetmapping.integer)
2417                 {
2418                         switch(rsurface.texture->offsetmapping)
2419                         {
2420                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2421                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2422                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423                         case OFFSETMAPPING_OFF: break;
2424                         }
2425                 }
2426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2428                 // lightmapped wall
2429                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2430                         permutation |= SHADERPERMUTATION_GLOW;
2431                 if (r_refdef.fogenabled)
2432                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2433                 if (rsurface.texture->colormapping)
2434                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2435                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2436                 {
2437                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2438                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2439
2440                         if (r_shadow_shadowmapsampler)
2441                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2442                         if (r_shadow_shadowmappcf > 1)
2443                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2444                         else if (r_shadow_shadowmappcf)
2445                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2446                 }
2447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2448                         permutation |= SHADERPERMUTATION_REFLECTION;
2449                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2450                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2451                 if (rsurface.texture->reflectmasktexture)
2452                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2453                 if (FAKELIGHT_ENABLED)
2454                 {
2455                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2456                         mode = SHADERMODE_FAKELIGHT;
2457                         permutation |= SHADERPERMUTATION_DIFFUSE;
2458                         if (specularscale > 0)
2459                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2460                 }
2461                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2462                 {
2463                         // deluxemapping (light direction texture)
2464                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2466                         else
2467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 2)
2473                 {
2474                         // fake deluxemapping (uniform light direction in tangentspace)
2475                         if (rsurface.uselightmaptexture)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (rsurface.uselightmaptexture)
2484                 {
2485                         // ordinary lightmapping (q1bsp, q3bsp)
2486                         mode = SHADERMODE_LIGHTMAP;
2487                 }
2488                 else
2489                 {
2490                         // ordinary vertex coloring (q3bsp)
2491                         mode = SHADERMODE_VERTEXCOLOR;
2492                 }
2493                 if (r_shadow_bouncegridtexture)
2494                 {
2495                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2496                         if (r_shadow_bouncegriddirectional)
2497                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2498                 }
2499                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2500                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 // when using alphatocoverage, we don't need alphakill
2502                 if (vid.allowalphatocoverage)
2503                 {
2504                         if (r_transparent_alphatocoverage.integer)
2505                         {
2506                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2507                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2508                         }
2509                         else
2510                                 GL_AlphaToCoverage(false);
2511                 }
2512         }
2513         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2514                 colormod = dummy_colormod;
2515         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2516                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2517         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2518                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2519         switch(vid.renderpath)
2520         {
2521         case RENDERPATH_D3D9:
2522 #ifdef SUPPORTD3D
2523                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2524                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2525                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2527                 if (mode == SHADERMODE_LIGHTSOURCE)
2528                 {
2529                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2530                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                 }
2532                 else
2533                 {
2534                         if (mode == SHADERMODE_LIGHTDIRECTION)
2535                         {
2536                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2537                         }
2538                 }
2539                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2542                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2543                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2544
2545                 if (mode == SHADERMODE_LIGHTSOURCE)
2546                 {
2547                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2552
2553                         // additive passes are only darkened by fog, not tinted
2554                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2555                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2556                 }
2557                 else
2558                 {
2559                         if (mode == SHADERMODE_FLATCOLOR)
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2562                         }
2563                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2564                         {
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2572                         }
2573                         else
2574                         {
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2580                         }
2581                         // additive passes are only darkened by fog, not tinted
2582                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2584                         else
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2586                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2587                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2594                         if (mode == SHADERMODE_WATER)
2595                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2596                 }
2597                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2598                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2599                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2601                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2602                 if (rsurface.texture->pantstexture)
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2604                 else
2605                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2606                 if (rsurface.texture->shirttexture)
2607                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2608                 else
2609                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2610                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2611                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2614                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2615                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2616                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2617                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2619                         );
2620                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2621                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2622
2623                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2624                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2625                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2626                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2627                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2631                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2632                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2633                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2634                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2635                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2636                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2637                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2638                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2639                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2640                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2641                 {
2642                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2643                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2644                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646                 else
2647                 {
2648                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2649                 }
2650 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2651 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2652                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2653                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2654                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2655                 {
2656                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2657                         if (rsurface.rtlight)
2658                         {
2659                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2660                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2661                         }
2662                 }
2663 #endif
2664                 break;
2665         case RENDERPATH_D3D10:
2666                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2667                 break;
2668         case RENDERPATH_D3D11:
2669                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2670                 break;
2671         case RENDERPATH_GL20:
2672         case RENDERPATH_GLES2:
2673                 if (!vid.useinterleavedarrays)
2674                 {
2675                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2676                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2677                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2683                 }
2684                 else
2685                 {
2686                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2687                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2688                 }
2689                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2690                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2691                 if (mode == SHADERMODE_LIGHTSOURCE)
2692                 {
2693                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2694                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2695                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2696                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2697                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2698                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2699         
2700                         // additive passes are only darkened by fog, not tinted
2701                         if (r_glsl_permutation->loc_FogColor >= 0)
2702                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2703                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2704                 }
2705                 else
2706                 {
2707                         if (mode == SHADERMODE_FLATCOLOR)
2708                         {
2709                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2710                         }
2711                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2712                         {
2713                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2714                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2715                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2716                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2717                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2718                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2719                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2720                         }
2721                         else
2722                         {
2723                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2724                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2725                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2726                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2728                         }
2729                         // additive passes are only darkened by fog, not tinted
2730                         if (r_glsl_permutation->loc_FogColor >= 0)
2731                         {
2732                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2733                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2734                                 else
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2736                         }
2737                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2738                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2739                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2740                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2741                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2742                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2743                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2744                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2745                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2746                 }
2747                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2748                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2751                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2752
2753                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2754                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2755                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2756                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2757                 {
2758                         if (rsurface.texture->pantstexture)
2759                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2760                         else
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2762                 }
2763                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2764                 {
2765                         if (rsurface.texture->shirttexture)
2766                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2767                         else
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2769                 }
2770                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2771                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2772                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2773                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2774                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2775                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2776                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2777                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2779                         );
2780                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2781                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2782                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2783                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2784
2785                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2786                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2787                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2788                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2789                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2790                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2791                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2796                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2797                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2798                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2799                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2800                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2801                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2802                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2803                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2804                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2805                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2806                 {
2807                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2808                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2809                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2810                 }
2811                 else
2812                 {
2813                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2814                 }
2815                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2816                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2817                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2818                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2819                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2820                 {
2821                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2822                         if (rsurface.rtlight)
2823                         {
2824                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2825                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2826                         }
2827                 }
2828                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2829                 CHECKGLERROR
2830                 break;
2831         case RENDERPATH_GL11:
2832         case RENDERPATH_GL13:
2833         case RENDERPATH_GLES1:
2834                 break;
2835         case RENDERPATH_SOFT:
2836                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2837                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2838                 R_SetupShader_SetPermutationSoft(mode, permutation);
2839                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2840                 if (mode == SHADERMODE_LIGHTSOURCE)
2841                 {
2842                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2848         
2849                         // additive passes are only darkened by fog, not tinted
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2851                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2852                 }
2853                 else
2854                 {
2855                         if (mode == SHADERMODE_FLATCOLOR)
2856                         {
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2858                         }
2859                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2860                         {
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2868                         }
2869                         else
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2876                         }
2877                         // additive passes are only darkened by fog, not tinted
2878                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2880                         else
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2882                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2883                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2884                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2885                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2886                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2889                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2890                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2891                 }
2892                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2893                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2894                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2895                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2896                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2897
2898                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2899                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2900                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2901                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2902                 {
2903                         if (rsurface.texture->pantstexture)
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2905                         else
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2907                 }
2908                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2909                 {
2910                         if (rsurface.texture->shirttexture)
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2912                         else
2913                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2914                 }
2915                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2919                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2920                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2921                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2922                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2924                         );
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2927
2928                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2929                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2930                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2931                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2940                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2941                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2942                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2943                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2944                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2945                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2946                 {
2947                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2948                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2949                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2950                 }
2951                 else
2952                 {
2953                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954                 }
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2991         // light source
2992         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2993         if (rtlight->currentcubemap != r_texture_whitecube)
2994                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2995         if (diffusescale > 0)
2996                 permutation |= SHADERPERMUTATION_DIFFUSE;
2997         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2998                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2999         if (r_shadow_usingshadowmap2d)
3000         {
3001                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3002                 if (r_shadow_shadowmapvsdct)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3004
3005                 if (r_shadow_shadowmapsampler)
3006                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3007                 if (r_shadow_shadowmappcf > 1)
3008                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3009                 else if (r_shadow_shadowmappcf)
3010                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3011         }
3012         if (vid.allowalphatocoverage)
3013                 GL_AlphaToCoverage(false);
3014         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3015         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3016         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3017         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3018         switch(vid.renderpath)
3019         {
3020         case RENDERPATH_D3D9:
3021 #ifdef SUPPORTD3D
3022                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3024                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3028                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3029                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3030                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3031                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3033
3034                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3035                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3036                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3037                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3038                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3039                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3040 #endif
3041                 break;
3042         case RENDERPATH_D3D10:
3043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3044                 break;
3045         case RENDERPATH_D3D11:
3046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3047                 break;
3048         case RENDERPATH_GL20:
3049         case RENDERPATH_GLES2:
3050                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3051                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3052                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3053                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3054                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3055                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3056                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3057                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3058                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3059                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3060                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3061
3062                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3063                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3064                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3065                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3066                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3067                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3068                 break;
3069         case RENDERPATH_GL11:
3070         case RENDERPATH_GL13:
3071         case RENDERPATH_GLES1:
3072                 break;
3073         case RENDERPATH_SOFT:
3074                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3076                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3081                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3082                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3083                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3084                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3085
3086                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3087                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3088                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3089                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3090                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3091                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3092                 break;
3093         }
3094 }
3095
3096 #define SKINFRAME_HASH 1024
3097
3098 typedef struct
3099 {
3100         int loadsequence; // incremented each level change
3101         memexpandablearray_t array;
3102         skinframe_t *hash[SKINFRAME_HASH];
3103 }
3104 r_skinframe_t;
3105 r_skinframe_t r_skinframe;
3106
3107 void R_SkinFrame_PrepareForPurge(void)
3108 {
3109         r_skinframe.loadsequence++;
3110         // wrap it without hitting zero
3111         if (r_skinframe.loadsequence >= 200)
3112                 r_skinframe.loadsequence = 1;
3113 }
3114
3115 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3116 {
3117         if (!skinframe)
3118                 return;
3119         // mark the skinframe as used for the purging code
3120         skinframe->loadsequence = r_skinframe.loadsequence;
3121 }
3122
3123 void R_SkinFrame_Purge(void)
3124 {
3125         int i;
3126         skinframe_t *s;
3127         for (i = 0;i < SKINFRAME_HASH;i++)
3128         {
3129                 for (s = r_skinframe.hash[i];s;s = s->next)
3130                 {
3131                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3132                         {
3133                                 if (s->merged == s->base)
3134                                         s->merged = NULL;
3135                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3136                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3137                                 R_PurgeTexture(s->merged);s->merged = NULL;
3138                                 R_PurgeTexture(s->base  );s->base   = NULL;
3139                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3140                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3141                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3142                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3143                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3144                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3145                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3146                                 s->loadsequence = 0;
3147                         }
3148                 }
3149         }
3150 }
3151
3152 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3153         skinframe_t *item;
3154         char basename[MAX_QPATH];
3155
3156         Image_StripImageExtension(name, basename, sizeof(basename));
3157
3158         if( last == NULL ) {
3159                 int hashindex;
3160                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3161                 item = r_skinframe.hash[hashindex];
3162         } else {
3163                 item = last->next;
3164         }
3165
3166         // linearly search through the hash bucket
3167         for( ; item ; item = item->next ) {
3168                 if( !strcmp( item->basename, basename ) ) {
3169                         return item;
3170                 }
3171         }
3172         return NULL;
3173 }
3174
3175 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3176 {
3177         skinframe_t *item;
3178         int hashindex;
3179         char basename[MAX_QPATH];
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3185                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3186                         break;
3187
3188         if (!item) {
3189                 rtexture_t *dyntexture;
3190                 // check whether its a dynamic texture
3191                 dyntexture = CL_GetDynTexture( basename );
3192                 if (!add && !dyntexture)
3193                         return NULL;
3194                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3195                 memset(item, 0, sizeof(*item));
3196                 strlcpy(item->basename, basename, sizeof(item->basename));
3197                 item->base = dyntexture; // either NULL or dyntexture handle
3198                 item->textureflags = textureflags;
3199                 item->comparewidth = comparewidth;
3200                 item->compareheight = compareheight;
3201                 item->comparecrc = comparecrc;
3202                 item->next = r_skinframe.hash[hashindex];
3203                 r_skinframe.hash[hashindex] = item;
3204         }
3205         else if( item->base == NULL )
3206         {
3207                 rtexture_t *dyntexture;
3208                 // check whether its a dynamic texture
3209                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3210                 dyntexture = CL_GetDynTexture( basename );
3211                 item->base = dyntexture; // either NULL or dyntexture handle
3212         }
3213
3214         R_SkinFrame_MarkUsed(item);
3215         return item;
3216 }
3217
3218 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3219         { \
3220                 unsigned long long avgcolor[5], wsum; \
3221                 int pix, comp, w; \
3222                 avgcolor[0] = 0; \
3223                 avgcolor[1] = 0; \
3224                 avgcolor[2] = 0; \
3225                 avgcolor[3] = 0; \
3226                 avgcolor[4] = 0; \
3227                 wsum = 0; \
3228                 for(pix = 0; pix < cnt; ++pix) \
3229                 { \
3230                         w = 0; \
3231                         for(comp = 0; comp < 3; ++comp) \
3232                                 w += getpixel; \
3233                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3234                         { \
3235                                 ++wsum; \
3236                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3237                                 w = getpixel; \
3238                                 for(comp = 0; comp < 3; ++comp) \
3239                                         avgcolor[comp] += getpixel * w; \
3240                                 avgcolor[3] += w; \
3241                         } \
3242                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3243                         avgcolor[4] += getpixel; \
3244                 } \
3245                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3246                         avgcolor[3] = 1; \
3247                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3248                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3249                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3250                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3251         }
3252
3253 extern cvar_t gl_picmip;
3254 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3255 {
3256         int j;
3257         unsigned char *pixels;
3258         unsigned char *bumppixels;
3259         unsigned char *basepixels = NULL;
3260         int basepixels_width = 0;
3261         int basepixels_height = 0;
3262         skinframe_t *skinframe;
3263         rtexture_t *ddsbase = NULL;
3264         qboolean ddshasalpha = false;
3265         float ddsavgcolor[4];
3266         char basename[MAX_QPATH];
3267         int miplevel = R_PicmipForFlags(textureflags);
3268         int savemiplevel = miplevel;
3269         int mymiplevel;
3270
3271         if (cls.state == ca_dedicated)
3272                 return NULL;
3273
3274         // return an existing skinframe if already loaded
3275         // if loading of the first image fails, don't make a new skinframe as it
3276         // would cause all future lookups of this to be missing
3277         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3278         if (skinframe && skinframe->base)
3279                 return skinframe;
3280
3281         Image_StripImageExtension(name, basename, sizeof(basename));
3282
3283         // check for DDS texture file first
3284         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3285         {
3286                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3287                 if (basepixels == NULL)
3288                         return NULL;
3289         }
3290
3291         // FIXME handle miplevel
3292
3293         if (developer_loading.integer)
3294                 Con_Printf("loading skin \"%s\"\n", name);
3295
3296         // we've got some pixels to store, so really allocate this new texture now
3297         if (!skinframe)
3298                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3299         skinframe->stain = NULL;
3300         skinframe->merged = NULL;
3301         skinframe->base = NULL;
3302         skinframe->pants = NULL;
3303         skinframe->shirt = NULL;
3304         skinframe->nmap = NULL;
3305         skinframe->gloss = NULL;
3306         skinframe->glow = NULL;
3307         skinframe->fog = NULL;
3308         skinframe->reflect = NULL;
3309         skinframe->hasalpha = false;
3310
3311         if (ddsbase)
3312         {
3313                 skinframe->base = ddsbase;
3314                 skinframe->hasalpha = ddshasalpha;
3315                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3316                 if (r_loadfog && skinframe->hasalpha)
3317                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3318                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3319         }
3320         else
3321         {
3322                 basepixels_width = image_width;
3323                 basepixels_height = image_height;
3324                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3325                 if (textureflags & TEXF_ALPHA)
3326                 {
3327                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3328                         {
3329                                 if (basepixels[j] < 255)
3330                                 {
3331                                         skinframe->hasalpha = true;
3332                                         break;
3333                                 }
3334                         }
3335                         if (r_loadfog && skinframe->hasalpha)
3336                         {
3337                                 // has transparent pixels
3338                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3339                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3340                                 {
3341                                         pixels[j+0] = 255;
3342                                         pixels[j+1] = 255;
3343                                         pixels[j+2] = 255;
3344                                         pixels[j+3] = basepixels[j+3];
3345                                 }
3346                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3347                                 Mem_Free(pixels);
3348                         }
3349                 }
3350                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3351 #ifndef USE_GLES2
3352                 //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]);
3353                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3354                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3355                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3356                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3357 #endif
3358         }
3359
3360         if (r_loaddds)
3361         {
3362                 mymiplevel = savemiplevel;
3363                 if (r_loadnormalmap)
3364                         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);
3365                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3366                 if (r_loadgloss)
3367                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3368                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3369                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3370                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3371         }
3372
3373         // _norm is the name used by tenebrae and has been adopted as standard
3374         if (r_loadnormalmap && skinframe->nmap == NULL)
3375         {
3376                 mymiplevel = savemiplevel;
3377                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3378                 {
3379                         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);
3380                         Mem_Free(pixels);
3381                         pixels = NULL;
3382                 }
3383                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3384                 {
3385                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3386                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3387                         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);
3388                         Mem_Free(pixels);
3389                         Mem_Free(bumppixels);
3390                 }
3391                 else if (r_shadow_bumpscale_basetexture.value > 0)
3392                 {
3393                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3394                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3395                         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);
3396                         Mem_Free(pixels);
3397                 }
3398 #ifndef USE_GLES2
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3400                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401 #endif
3402         }
3403
3404         // _luma is supported only for tenebrae compatibility
3405         // _glow is the preferred name
3406         mymiplevel = savemiplevel;
3407         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))))
3408         {
3409                 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);
3410 #ifndef USE_GLES2
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3412                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3413 #endif
3414                 Mem_Free(pixels);pixels = NULL;
3415         }
3416
3417         mymiplevel = savemiplevel;
3418         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3419         {
3420                 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);
3421 #ifndef USE_GLES2
3422                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3423                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3424 #endif
3425                 Mem_Free(pixels);
3426                 pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3431         {
3432                 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);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3435                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3436 #endif
3437                 Mem_Free(pixels);
3438                 pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 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);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3447                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3459                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         if (basepixels)
3466                 Mem_Free(basepixels);
3467
3468         return skinframe;
3469 }
3470
3471 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3472 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3473 {
3474         int i;
3475         unsigned char *temp1, *temp2;
3476         skinframe_t *skinframe;
3477
3478         if (cls.state == ca_dedicated)
3479                 return NULL;
3480
3481         // if already loaded just return it, otherwise make a new skinframe
3482         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3483         if (skinframe && skinframe->base)
3484                 return skinframe;
3485
3486         skinframe->stain = NULL;
3487         skinframe->merged = NULL;
3488         skinframe->base = NULL;
3489         skinframe->pants = NULL;
3490         skinframe->shirt = NULL;
3491         skinframe->nmap = NULL;
3492         skinframe->gloss = NULL;
3493         skinframe->glow = NULL;
3494         skinframe->fog = NULL;
3495         skinframe->reflect = NULL;
3496         skinframe->hasalpha = false;
3497
3498         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3499         if (!skindata)
3500                 return NULL;
3501
3502         if (developer_loading.integer)
3503                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3504
3505         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3506         {
3507                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3508                 temp2 = temp1 + width * height * 4;
3509                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3510                 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);
3511                 Mem_Free(temp1);
3512         }
3513         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3514         if (textureflags & TEXF_ALPHA)
3515         {
3516                 for (i = 3;i < width * height * 4;i += 4)
3517                 {
3518                         if (skindata[i] < 255)
3519                         {
3520                                 skinframe->hasalpha = true;
3521                                 break;
3522                         }
3523                 }
3524                 if (r_loadfog && skinframe->hasalpha)
3525                 {
3526                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3527                         memcpy(fogpixels, skindata, width * height * 4);
3528                         for (i = 0;i < width * height * 4;i += 4)
3529                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3530                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3531                         Mem_Free(fogpixels);
3532                 }
3533         }
3534
3535         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3536         //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]);
3537
3538         return skinframe;
3539 }
3540
3541 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3542 {
3543         int i;
3544         int featuresmask;
3545         skinframe_t *skinframe;
3546
3547         if (cls.state == ca_dedicated)
3548                 return NULL;
3549
3550         // if already loaded just return it, otherwise make a new skinframe
3551         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3552         if (skinframe && skinframe->base)
3553                 return skinframe;
3554
3555         skinframe->stain = NULL;
3556         skinframe->merged = NULL;
3557         skinframe->base = NULL;
3558         skinframe->pants = NULL;
3559         skinframe->shirt = NULL;
3560         skinframe->nmap = NULL;
3561         skinframe->gloss = NULL;
3562         skinframe->glow = NULL;
3563         skinframe->fog = NULL;
3564         skinframe->reflect = NULL;
3565         skinframe->hasalpha = false;
3566
3567         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3568         if (!skindata)
3569                 return NULL;
3570
3571         if (developer_loading.integer)
3572                 Con_Printf("loading quake skin \"%s\"\n", name);
3573
3574         // 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)
3575         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3576         memcpy(skinframe->qpixels, skindata, width*height);
3577         skinframe->qwidth = width;
3578         skinframe->qheight = height;
3579
3580         featuresmask = 0;
3581         for (i = 0;i < width * height;i++)
3582                 featuresmask |= palette_featureflags[skindata[i]];
3583
3584         skinframe->hasalpha = false;
3585         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3586         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3587         skinframe->qgeneratemerged = true;
3588         skinframe->qgeneratebase = skinframe->qhascolormapping;
3589         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3590
3591         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3592         //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]);
3593
3594         return skinframe;
3595 }
3596
3597 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3598 {
3599         int width;
3600         int height;
3601         unsigned char *skindata;
3602
3603         if (!skinframe->qpixels)
3604                 return;
3605
3606         if (!skinframe->qhascolormapping)
3607                 colormapped = false;
3608
3609         if (colormapped)
3610         {
3611                 if (!skinframe->qgeneratebase)
3612                         return;
3613         }
3614         else
3615         {
3616                 if (!skinframe->qgeneratemerged)
3617                         return;
3618         }
3619
3620         width = skinframe->qwidth;
3621         height = skinframe->qheight;
3622         skindata = skinframe->qpixels;
3623
3624         if (skinframe->qgeneratenmap)
3625         {
3626                 unsigned char *temp1, *temp2;
3627                 skinframe->qgeneratenmap = false;
3628                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3629                 temp2 = temp1 + width * height * 4;
3630                 // use either a custom palette or the quake palette
3631                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3632                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3633                 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);
3634                 Mem_Free(temp1);
3635         }
3636
3637         if (skinframe->qgenerateglow)
3638         {
3639                 skinframe->qgenerateglow = false;
3640                 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
3641         }
3642
3643         if (colormapped)
3644         {
3645                 skinframe->qgeneratebase = false;
3646                 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);
3647                 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);
3648                 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);
3649         }
3650         else
3651         {
3652                 skinframe->qgeneratemerged = false;
3653                 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);
3654         }
3655
3656         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3657         {
3658                 Mem_Free(skinframe->qpixels);
3659                 skinframe->qpixels = NULL;
3660         }
3661 }
3662
3663 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)
3664 {
3665         int i;
3666         skinframe_t *skinframe;
3667
3668         if (cls.state == ca_dedicated)
3669                 return NULL;
3670
3671         // if already loaded just return it, otherwise make a new skinframe
3672         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3673         if (skinframe && skinframe->base)
3674                 return skinframe;
3675
3676         skinframe->stain = NULL;
3677         skinframe->merged = NULL;
3678         skinframe->base = NULL;
3679         skinframe->pants = NULL;
3680         skinframe->shirt = NULL;
3681         skinframe->nmap = NULL;
3682         skinframe->gloss = NULL;
3683         skinframe->glow = NULL;
3684         skinframe->fog = NULL;
3685         skinframe->reflect = NULL;
3686         skinframe->hasalpha = false;
3687
3688         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3689         if (!skindata)
3690                 return NULL;
3691
3692         if (developer_loading.integer)
3693                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3694
3695         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3696         if (textureflags & TEXF_ALPHA)
3697         {
3698                 for (i = 0;i < width * height;i++)
3699                 {
3700                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3701                         {
3702                                 skinframe->hasalpha = true;
3703                                 break;
3704                         }
3705                 }
3706                 if (r_loadfog && skinframe->hasalpha)
3707                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3708         }
3709
3710         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3711         //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]);
3712
3713         return skinframe;
3714 }
3715
3716 skinframe_t *R_SkinFrame_LoadMissing(void)
3717 {
3718         skinframe_t *skinframe;
3719
3720         if (cls.state == ca_dedicated)
3721                 return NULL;
3722
3723         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3724         skinframe->stain = NULL;
3725         skinframe->merged = NULL;
3726         skinframe->base = NULL;
3727         skinframe->pants = NULL;
3728         skinframe->shirt = NULL;
3729         skinframe->nmap = NULL;
3730         skinframe->gloss = NULL;
3731         skinframe->glow = NULL;
3732         skinframe->fog = NULL;
3733         skinframe->reflect = NULL;
3734         skinframe->hasalpha = false;
3735
3736         skinframe->avgcolor[0] = rand() / RAND_MAX;
3737         skinframe->avgcolor[1] = rand() / RAND_MAX;
3738         skinframe->avgcolor[2] = rand() / RAND_MAX;
3739         skinframe->avgcolor[3] = 1;
3740
3741         return skinframe;
3742 }
3743
3744 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3745 typedef struct suffixinfo_s
3746 {
3747         const char *suffix;
3748         qboolean flipx, flipy, flipdiagonal;
3749 }
3750 suffixinfo_t;
3751 static suffixinfo_t suffix[3][6] =
3752 {
3753         {
3754                 {"px",   false, false, false},
3755                 {"nx",   false, false, false},
3756                 {"py",   false, false, false},
3757                 {"ny",   false, false, false},
3758                 {"pz",   false, false, false},
3759                 {"nz",   false, false, false}
3760         },
3761         {
3762                 {"posx", false, false, false},
3763                 {"negx", false, false, false},
3764                 {"posy", false, false, false},
3765                 {"negy", false, false, false},
3766                 {"posz", false, false, false},
3767                 {"negz", false, false, false}
3768         },
3769         {
3770                 {"rt",    true, false,  true},
3771                 {"lf",   false,  true,  true},
3772                 {"ft",    true,  true, false},
3773                 {"bk",   false, false, false},
3774                 {"up",    true, false,  true},
3775                 {"dn",    true, false,  true}
3776         }
3777 };
3778
3779 static int componentorder[4] = {0, 1, 2, 3};
3780
3781 rtexture_t *R_LoadCubemap(const char *basename)
3782 {
3783         int i, j, cubemapsize;
3784         unsigned char *cubemappixels, *image_buffer;
3785         rtexture_t *cubemaptexture;
3786         char name[256];
3787         // must start 0 so the first loadimagepixels has no requested width/height
3788         cubemapsize = 0;
3789         cubemappixels = NULL;
3790         cubemaptexture = NULL;
3791         // keep trying different suffix groups (posx, px, rt) until one loads
3792         for (j = 0;j < 3 && !cubemappixels;j++)
3793         {
3794                 // load the 6 images in the suffix group
3795                 for (i = 0;i < 6;i++)
3796                 {
3797                         // generate an image name based on the base and and suffix
3798                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3799                         // load it
3800                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3801                         {
3802                                 // an image loaded, make sure width and height are equal
3803                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3804                                 {
3805                                         // if this is the first image to load successfully, allocate the cubemap memory
3806                                         if (!cubemappixels && image_width >= 1)
3807                                         {
3808                                                 cubemapsize = image_width;
3809                                                 // note this clears to black, so unavailable sides are black
3810                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3811                                         }
3812                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3813                                         if (cubemappixels)
3814                                                 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);
3815                                 }
3816                                 else
3817                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3818                                 // free the image
3819                                 Mem_Free(image_buffer);
3820                         }
3821                 }
3822         }
3823         // if a cubemap loaded, upload it
3824         if (cubemappixels)
3825         {
3826                 if (developer_loading.integer)
3827                         Con_Printf("loading cubemap \"%s\"\n", basename);
3828
3829                 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);
3830                 Mem_Free(cubemappixels);
3831         }
3832         else
3833         {
3834                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3835                 if (developer_loading.integer)
3836                 {
3837                         Con_Printf("(tried tried images ");
3838                         for (j = 0;j < 3;j++)
3839                                 for (i = 0;i < 6;i++)
3840                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3841                         Con_Print(" and was unable to find any of them).\n");
3842                 }
3843         }
3844         return cubemaptexture;
3845 }
3846
3847 rtexture_t *R_GetCubemap(const char *basename)
3848 {
3849         int i;
3850         for (i = 0;i < r_texture_numcubemaps;i++)
3851                 if (r_texture_cubemaps[i] != NULL)
3852                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3853                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3854         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3855                 return r_texture_whitecube;
3856         r_texture_numcubemaps++;
3857         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3858         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3859         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3860         return r_texture_cubemaps[i]->texture;
3861 }
3862
3863 void R_FreeCubemap(const char *basename)
3864 {
3865         int i;
3866
3867         for (i = 0;i < r_texture_numcubemaps;i++)
3868         {
3869                 if (r_texture_cubemaps[i] != NULL)
3870                 {
3871                         if (r_texture_cubemaps[i]->texture)
3872                         {
3873                                 if (developer_loading.integer)
3874                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3875                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3876                                 Mem_Free(r_texture_cubemaps[i]);
3877                                 r_texture_cubemaps[i] = NULL;
3878                         }
3879                 }
3880         }
3881 }
3882
3883 void R_FreeCubemaps(void)
3884 {
3885         int i;
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887         {
3888                 if (developer_loading.integer)
3889                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3890                 if (r_texture_cubemaps[i] != NULL)
3891                 {
3892                         if (r_texture_cubemaps[i]->texture)
3893                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3894                         Mem_Free(r_texture_cubemaps[i]);
3895                 }
3896         }
3897         r_texture_numcubemaps = 0;
3898 }
3899
3900 void R_Main_FreeViewCache(void)
3901 {
3902         if (r_refdef.viewcache.entityvisible)
3903                 Mem_Free(r_refdef.viewcache.entityvisible);
3904         if (r_refdef.viewcache.world_pvsbits)
3905                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3906         if (r_refdef.viewcache.world_leafvisible)
3907                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908         if (r_refdef.viewcache.world_surfacevisible)
3909                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3910         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3911 }
3912
3913 void R_Main_ResizeViewCache(void)
3914 {
3915         int numentities = r_refdef.scene.numentities;
3916         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3917         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3918         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3919         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3920         if (r_refdef.viewcache.maxentities < numentities)
3921         {
3922                 r_refdef.viewcache.maxentities = numentities;
3923                 if (r_refdef.viewcache.entityvisible)
3924                         Mem_Free(r_refdef.viewcache.entityvisible);
3925                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3926         }
3927         if (r_refdef.viewcache.world_numclusters != numclusters)
3928         {
3929                 r_refdef.viewcache.world_numclusters = numclusters;
3930                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3931                 if (r_refdef.viewcache.world_pvsbits)
3932                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3933                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3934         }
3935         if (r_refdef.viewcache.world_numleafs != numleafs)
3936         {
3937                 r_refdef.viewcache.world_numleafs = numleafs;
3938                 if (r_refdef.viewcache.world_leafvisible)
3939                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3940                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3941         }
3942         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3943         {
3944                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3945                 if (r_refdef.viewcache.world_surfacevisible)
3946                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3947                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3948         }
3949 }
3950
3951 extern rtexture_t *loadingscreentexture;
3952 void gl_main_start(void)
3953 {
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965
3966         r_loaddds = r_texture_dds_load.integer != 0;
3967         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3968
3969         switch(vid.renderpath)
3970         {
3971         case RENDERPATH_GL20:
3972         case RENDERPATH_D3D9:
3973         case RENDERPATH_D3D10:
3974         case RENDERPATH_D3D11:
3975         case RENDERPATH_SOFT:
3976         case RENDERPATH_GLES2:
3977                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3978                 Cvar_SetValueQuick(&gl_combine, 1);
3979                 Cvar_SetValueQuick(&r_glsl, 1);
3980                 r_loadnormalmap = true;
3981                 r_loadgloss = true;
3982                 r_loadfog = false;
3983                 break;
3984         case RENDERPATH_GL13:
3985         case RENDERPATH_GLES1:
3986                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3987                 Cvar_SetValueQuick(&gl_combine, 1);
3988                 Cvar_SetValueQuick(&r_glsl, 0);
3989                 r_loadnormalmap = false;
3990                 r_loadgloss = false;
3991                 r_loadfog = true;
3992                 break;
3993         case RENDERPATH_GL11:
3994                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3995                 Cvar_SetValueQuick(&gl_combine, 0);
3996                 Cvar_SetValueQuick(&r_glsl, 0);
3997                 r_loadnormalmap = false;
3998                 r_loadgloss = false;
3999                 r_loadfog = true;
4000                 break;
4001         }
4002
4003         R_AnimCache_Free();
4004         R_FrameData_Reset();
4005
4006         r_numqueries = 0;
4007         r_maxqueries = 0;
4008         memset(r_queries, 0, sizeof(r_queries));
4009
4010         r_qwskincache = NULL;
4011         r_qwskincache_size = 0;
4012
4013         // due to caching of texture_t references, the collision cache must be reset
4014         Collision_Cache_Reset(true);
4015
4016         // set up r_skinframe loading system for textures
4017         memset(&r_skinframe, 0, sizeof(r_skinframe));
4018         r_skinframe.loadsequence = 1;
4019         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4020
4021         r_main_texturepool = R_AllocTexturePool();
4022         R_BuildBlankTextures();
4023         R_BuildNoTexture();
4024         if (vid.support.arb_texture_cube_map)
4025         {
4026                 R_BuildWhiteCube();
4027                 R_BuildNormalizationCube();
4028         }
4029         r_texture_fogattenuation = NULL;
4030         r_texture_fogheighttexture = NULL;
4031         r_texture_gammaramps = NULL;
4032         //r_texture_fogintensity = NULL;
4033         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4034         memset(&r_waterstate, 0, sizeof(r_waterstate));
4035         r_glsl_permutation = NULL;
4036         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4037         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4038         glslshaderstring = NULL;
4039 #ifdef SUPPORTD3D
4040         r_hlsl_permutation = NULL;
4041         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4042         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4043 #endif
4044         hlslshaderstring = NULL;
4045         memset(&r_svbsp, 0, sizeof (r_svbsp));
4046
4047         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4048         r_texture_numcubemaps = 0;
4049
4050         r_refdef.fogmasktable_density = 0;
4051 }
4052
4053 void gl_main_shutdown(void)
4054 {
4055         R_AnimCache_Free();
4056         R_FrameData_Reset();
4057
4058         R_Main_FreeViewCache();
4059
4060         switch(vid.renderpath)
4061         {
4062         case RENDERPATH_GL11:
4063         case RENDERPATH_GL13:
4064         case RENDERPATH_GL20:
4065         case RENDERPATH_GLES1:
4066         case RENDERPATH_GLES2:
4067 #ifdef GL_SAMPLES_PASSED_ARB
4068                 if (r_maxqueries)
4069                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4070 #endif
4071                 break;
4072         case RENDERPATH_D3D9:
4073                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4074                 break;
4075         case RENDERPATH_D3D10:
4076                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4077                 break;
4078         case RENDERPATH_D3D11:
4079                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4080                 break;
4081         case RENDERPATH_SOFT:
4082                 break;
4083         }
4084
4085         r_numqueries = 0;
4086         r_maxqueries = 0;
4087         memset(r_queries, 0, sizeof(r_queries));
4088
4089         r_qwskincache = NULL;
4090         r_qwskincache_size = 0;
4091
4092         // clear out the r_skinframe state
4093         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4094         memset(&r_skinframe, 0, sizeof(r_skinframe));
4095
4096         if (r_svbsp.nodes)
4097                 Mem_Free(r_svbsp.nodes);
4098         memset(&r_svbsp, 0, sizeof (r_svbsp));
4099         R_FreeTexturePool(&r_main_texturepool);
4100         loadingscreentexture = NULL;
4101         r_texture_blanknormalmap = NULL;
4102         r_texture_white = NULL;
4103         r_texture_grey128 = NULL;
4104         r_texture_black = NULL;
4105         r_texture_whitecube = NULL;
4106         r_texture_normalizationcube = NULL;
4107         r_texture_fogattenuation = NULL;
4108         r_texture_fogheighttexture = NULL;
4109         r_texture_gammaramps = NULL;
4110         r_texture_numcubemaps = 0;
4111         //r_texture_fogintensity = NULL;
4112         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4113         memset(&r_waterstate, 0, sizeof(r_waterstate));
4114         R_GLSL_Restart_f();
4115
4116         r_glsl_permutation = NULL;
4117         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4118         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4119         glslshaderstring = NULL;
4120 #ifdef SUPPORTD3D
4121         r_hlsl_permutation = NULL;
4122         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4123         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4124 #endif
4125         hlslshaderstring = NULL;
4126 }
4127
4128 extern void CL_ParseEntityLump(char *entitystring);
4129 void gl_main_newmap(void)
4130 {
4131         // FIXME: move this code to client
4132         char *entities, entname[MAX_QPATH];
4133         if (r_qwskincache)
4134                 Mem_Free(r_qwskincache);
4135         r_qwskincache = NULL;
4136         r_qwskincache_size = 0;
4137         if (cl.worldmodel)
4138         {
4139                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4140                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4141                 {
4142                         CL_ParseEntityLump(entities);
4143                         Mem_Free(entities);
4144                         return;
4145                 }
4146                 if (cl.worldmodel->brush.entities)
4147                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4148         }
4149         R_Main_FreeViewCache();
4150
4151         R_FrameData_Reset();
4152 }
4153
4154 void GL_Main_Init(void)
4155 {
4156         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4157
4158         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4159         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4160         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4161         if (gamemode == GAME_NEHAHRA)
4162         {
4163                 Cvar_RegisterVariable (&gl_fogenable);
4164                 Cvar_RegisterVariable (&gl_fogdensity);
4165                 Cvar_RegisterVariable (&gl_fogred);
4166                 Cvar_RegisterVariable (&gl_foggreen);
4167                 Cvar_RegisterVariable (&gl_fogblue);
4168                 Cvar_RegisterVariable (&gl_fogstart);
4169                 Cvar_RegisterVariable (&gl_fogend);
4170                 Cvar_RegisterVariable (&gl_skyclip);
4171         }
4172         Cvar_RegisterVariable(&r_motionblur);
4173         Cvar_RegisterVariable(&r_damageblur);
4174         Cvar_RegisterVariable(&r_motionblur_averaging);
4175         Cvar_RegisterVariable(&r_motionblur_randomize);
4176         Cvar_RegisterVariable(&r_motionblur_minblur);
4177         Cvar_RegisterVariable(&r_motionblur_maxblur);
4178         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4179         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4180         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4181         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4182         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4183         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4184         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4185         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4186         Cvar_RegisterVariable(&r_equalize_entities_by);
4187         Cvar_RegisterVariable(&r_equalize_entities_to);
4188         Cvar_RegisterVariable(&r_depthfirst);
4189         Cvar_RegisterVariable(&r_useinfinitefarclip);
4190         Cvar_RegisterVariable(&r_farclip_base);
4191         Cvar_RegisterVariable(&r_farclip_world);
4192         Cvar_RegisterVariable(&r_nearclip);
4193         Cvar_RegisterVariable(&r_deformvertexes);
4194         Cvar_RegisterVariable(&r_transparent);
4195         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4196         Cvar_RegisterVariable(&r_showoverdraw);
4197         Cvar_RegisterVariable(&r_showbboxes);
4198         Cvar_RegisterVariable(&r_showsurfaces);
4199         Cvar_RegisterVariable(&r_showtris);
4200         Cvar_RegisterVariable(&r_shownormals);
4201         Cvar_RegisterVariable(&r_showlighting);
4202         Cvar_RegisterVariable(&r_showshadowvolumes);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4205         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4206         Cvar_RegisterVariable(&r_showdisabledepthtest);
4207         Cvar_RegisterVariable(&r_drawportals);
4208         Cvar_RegisterVariable(&r_drawentities);
4209         Cvar_RegisterVariable(&r_draw2d);
4210         Cvar_RegisterVariable(&r_drawworld);
4211         Cvar_RegisterVariable(&r_cullentities_trace);
4212         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4213         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4214         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4215         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4216         Cvar_RegisterVariable(&r_drawviewmodel);
4217         Cvar_RegisterVariable(&r_drawexteriormodel);
4218         Cvar_RegisterVariable(&r_speeds);
4219         Cvar_RegisterVariable(&r_fullbrights);
4220         Cvar_RegisterVariable(&r_wateralpha);
4221         Cvar_RegisterVariable(&r_dynamic);
4222         Cvar_RegisterVariable(&r_fakelight);
4223         Cvar_RegisterVariable(&r_fakelight_intensity);
4224         Cvar_RegisterVariable(&r_fullbright);
4225         Cvar_RegisterVariable(&r_shadows);
4226         Cvar_RegisterVariable(&r_shadows_darken);
4227         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4228         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4229         Cvar_RegisterVariable(&r_shadows_throwdistance);
4230         Cvar_RegisterVariable(&r_shadows_throwdirection);
4231         Cvar_RegisterVariable(&r_shadows_focus);
4232         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4233         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4235         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4237         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4238         Cvar_RegisterVariable(&r_fog_exp2);
4239         Cvar_RegisterVariable(&r_fog_clear);
4240         Cvar_RegisterVariable(&r_drawfog);
4241         Cvar_RegisterVariable(&r_transparentdepthmasking);
4242         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4243         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4244         Cvar_RegisterVariable(&r_texture_dds_load);
4245         Cvar_RegisterVariable(&r_texture_dds_save);
4246         Cvar_RegisterVariable(&r_textureunits);
4247         Cvar_RegisterVariable(&gl_combine);
4248         Cvar_RegisterVariable(&r_viewfbo);
4249         Cvar_RegisterVariable(&r_viewscale);
4250         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4256         Cvar_RegisterVariable(&r_glsl);
4257         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4264         Cvar_RegisterVariable(&r_glsl_postprocess);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4266         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4273
4274         Cvar_RegisterVariable(&r_water);
4275         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4276         Cvar_RegisterVariable(&r_water_clippingplanebias);
4277         Cvar_RegisterVariable(&r_water_refractdistort);
4278         Cvar_RegisterVariable(&r_water_reflectdistort);
4279         Cvar_RegisterVariable(&r_water_scissormode);
4280         Cvar_RegisterVariable(&r_water_lowquality);
4281
4282         Cvar_RegisterVariable(&r_lerpsprites);
4283         Cvar_RegisterVariable(&r_lerpmodels);
4284         Cvar_RegisterVariable(&r_lerplightstyles);
4285         Cvar_RegisterVariable(&r_waterscroll);
4286         Cvar_RegisterVariable(&r_bloom);
4287         Cvar_RegisterVariable(&r_bloom_colorscale);
4288         Cvar_RegisterVariable(&r_bloom_brighten);
4289         Cvar_RegisterVariable(&r_bloom_blur);
4290         Cvar_RegisterVariable(&r_bloom_resolution);
4291         Cvar_RegisterVariable(&r_bloom_colorexponent);
4292         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4293         Cvar_RegisterVariable(&r_hdr);
4294         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4295         Cvar_RegisterVariable(&r_hdr_glowintensity);
4296         Cvar_RegisterVariable(&r_hdr_range);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4298         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4300         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4304         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4305         Cvar_RegisterVariable(&developer_texturelogging);
4306         Cvar_RegisterVariable(&gl_lightmaps);
4307         Cvar_RegisterVariable(&r_test);
4308         Cvar_RegisterVariable(&r_glsl_saturation);
4309         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4310         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4311         Cvar_RegisterVariable(&r_framedatasize);
4312         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4313                 Cvar_SetValue("r_fullbrights", 0);
4314         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4315 }
4316
4317 extern void R_Textures_Init(void);
4318 extern void GL_Draw_Init(void);
4319 extern void GL_Main_Init(void);
4320 extern void R_Shadow_Init(void);
4321 extern void R_Sky_Init(void);
4322 extern void GL_Surf_Init(void);
4323 extern void R_Particles_Init(void);
4324 extern void R_Explosion_Init(void);
4325 extern void gl_backend_init(void);
4326 extern void Sbar_Init(void);
4327 extern void R_LightningBeams_Init(void);
4328 extern void Mod_RenderInit(void);
4329 extern void Font_Init(void);
4330
4331 void Render_Init(void)
4332 {
4333         gl_backend_init();
4334         R_Textures_Init();
4335         GL_Main_Init();
4336         Font_Init();
4337         GL_Draw_Init();
4338         R_Shadow_Init();
4339         R_Sky_Init();
4340         GL_Surf_Init();
4341         Sbar_Init();
4342         R_Particles_Init();
4343         R_Explosion_Init();
4344         R_LightningBeams_Init();
4345         Mod_RenderInit();
4346 }
4347
4348 /*
4349 ===============
4350 GL_Init
4351 ===============
4352 */
4353 #ifndef USE_GLES2
4354 extern char *ENGINE_EXTENSIONS;
4355 void GL_Init (void)
4356 {
4357         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4358         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4359         gl_version = (const char *)qglGetString(GL_VERSION);
4360         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4361
4362         if (!gl_extensions)
4363                 gl_extensions = "";
4364         if (!gl_platformextensions)
4365                 gl_platformextensions = "";
4366
4367         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4368         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4369         Con_Printf("GL_VERSION: %s\n", gl_version);
4370         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4371         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4372
4373         VID_CheckExtensions();
4374
4375         // LordHavoc: report supported extensions
4376         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4377
4378         // clear to black (loading plaque will be seen over this)
4379         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4380 }
4381 #endif
4382
4383 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4384 {
4385         int i;
4386         mplane_t *p;
4387         if (r_trippy.integer)
4388                 return false;
4389         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4390         {
4391                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4392                 if (i == 4)
4393                         continue;
4394                 p = r_refdef.view.frustum + i;
4395                 switch(p->signbits)
4396                 {
4397                 default:
4398                 case 0:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 1:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 2:
4407                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 3:
4411                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 4:
4415                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 5:
4419                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 case 6:
4423                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4424                                 return true;
4425                         break;
4426                 case 7:
4427                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 }
4431         }
4432         return false;
4433 }
4434
4435 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4436 {
4437         int i;
4438         const mplane_t *p;
4439         if (r_trippy.integer)
4440                 return false;
4441         for (i = 0;i < numplanes;i++)
4442         {
4443                 p = planes + i;
4444                 switch(p->signbits)
4445                 {
4446                 default:
4447                 case 0:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 1:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 2:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 3:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 4:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 5:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 case 6:
4472                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4473                                 return true;
4474                         break;
4475                 case 7:
4476                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 }
4480         }
4481         return false;
4482 }
4483
4484 //==================================================================================
4485
4486 // LordHavoc: this stores temporary data used within the same frame
4487
4488 typedef struct r_framedata_mem_s
4489 {
4490         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4491         size_t size; // how much usable space
4492         size_t current; // how much space in use
4493         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4494         size_t wantedsize; // how much space was allocated
4495         unsigned char *data; // start of real data (16byte aligned)
4496 }
4497 r_framedata_mem_t;
4498
4499 static r_framedata_mem_t *r_framedata_mem;
4500
4501 void R_FrameData_Reset(void)
4502 {
4503         while (r_framedata_mem)
4504         {
4505                 r_framedata_mem_t *next = r_framedata_mem->purge;
4506                 Mem_Free(r_framedata_mem);
4507                 r_framedata_mem = next;
4508         }
4509 }
4510
4511 void R_FrameData_Resize(void)
4512 {
4513         size_t wantedsize;
4514         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4515         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4516         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4517         {
4518                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4519                 newmem->wantedsize = wantedsize;
4520                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4521                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4522                 newmem->current = 0;
4523                 newmem->mark = 0;
4524                 newmem->purge = r_framedata_mem;
4525                 r_framedata_mem = newmem;
4526         }
4527 }
4528
4529 void R_FrameData_NewFrame(void)
4530 {
4531         R_FrameData_Resize();
4532         if (!r_framedata_mem)
4533                 return;
4534         // if we ran out of space on the last frame, free the old memory now
4535         while (r_framedata_mem->purge)
4536         {
4537                 // repeatedly remove the second item in the list, leaving only head
4538                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4539                 Mem_Free(r_framedata_mem->purge);
4540                 r_framedata_mem->purge = next;
4541         }
4542         // reset the current mem pointer
4543         r_framedata_mem->current = 0;
4544         r_framedata_mem->mark = 0;
4545 }
4546
4547 void *R_FrameData_Alloc(size_t size)
4548 {
4549         void *data;
4550
4551         // align to 16 byte boundary - the data pointer is already aligned, so we
4552         // only need to ensure the size of every allocation is also aligned
4553         size = (size + 15) & ~15;
4554
4555         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4556         {
4557                 // emergency - we ran out of space, allocate more memory
4558                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4559                 R_FrameData_Resize();
4560         }
4561
4562         data = r_framedata_mem->data + r_framedata_mem->current;
4563         r_framedata_mem->current += size;
4564
4565         // count the usage for stats
4566         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4567         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4568
4569         return (void *)data;
4570 }
4571
4572 void *R_FrameData_Store(size_t size, void *data)
4573 {
4574         void *d = R_FrameData_Alloc(size);
4575         if (d && data)
4576                 memcpy(d, data, size);
4577         return d;
4578 }
4579
4580 void R_FrameData_SetMark(void)
4581 {
4582         if (!r_framedata_mem)
4583                 return;
4584         r_framedata_mem->mark = r_framedata_mem->current;
4585 }
4586
4587 void R_FrameData_ReturnToMark(void)
4588 {
4589         if (!r_framedata_mem)
4590                 return;
4591         r_framedata_mem->current = r_framedata_mem->mark;
4592 }
4593
4594 //==================================================================================
4595
4596 // LordHavoc: animcache originally written by Echon, rewritten since then
4597
4598 /**
4599  * Animation cache prevents re-generating mesh data for an animated model
4600  * multiple times in one frame for lighting, shadowing, reflections, etc.
4601  */
4602
4603 void R_AnimCache_Free(void)
4604 {
4605 }
4606
4607 void R_AnimCache_ClearCache(void)
4608 {
4609         int i;
4610         entity_render_t *ent;
4611
4612         for (i = 0;i < r_refdef.scene.numentities;i++)
4613         {
4614                 ent = r_refdef.scene.entities[i];
4615                 ent->animcache_vertex3f = NULL;
4616                 ent->animcache_normal3f = NULL;
4617                 ent->animcache_svector3f = NULL;
4618                 ent->animcache_tvector3f = NULL;
4619                 ent->animcache_vertexmesh = NULL;
4620                 ent->animcache_vertex3fbuffer = NULL;
4621                 ent->animcache_vertexmeshbuffer = NULL;
4622         }
4623 }
4624
4625 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4626 {
4627         int i;
4628
4629         // check if we need the meshbuffers
4630         if (!vid.useinterleavedarrays)
4631                 return;
4632
4633         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4634                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4635         // TODO: upload vertex3f buffer?
4636         if (ent->animcache_vertexmesh)
4637         {
4638                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4639                 for (i = 0;i < numvertices;i++)
4640                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4641                 if (ent->animcache_svector3f)
4642                         for (i = 0;i < numvertices;i++)
4643                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4644                 if (ent->animcache_tvector3f)
4645                         for (i = 0;i < numvertices;i++)
4646                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4647                 if (ent->animcache_normal3f)
4648                         for (i = 0;i < numvertices;i++)
4649                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4650                 // TODO: upload vertexmeshbuffer?
4651         }
4652 }
4653
4654 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4655 {
4656         dp_model_t *model = ent->model;
4657         int numvertices;
4658         // see if it's already cached this frame
4659         if (ent->animcache_vertex3f)
4660         {
4661                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4662                 if (wantnormals || wanttangents)
4663                 {
4664                         if (ent->animcache_normal3f)
4665                                 wantnormals = false;
4666                         if (ent->animcache_svector3f)
4667                                 wanttangents = false;
4668                         if (wantnormals || wanttangents)
4669                         {
4670                                 numvertices = model->surfmesh.num_vertices;
4671                                 if (wantnormals)
4672                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                                 if (wanttangents)
4674                                 {
4675                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4676                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                                 }
4678                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4679                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4680                         }
4681                 }
4682         }
4683         else
4684         {
4685                 // see if this ent is worth caching
4686                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4687                         return false;
4688                 // get some memory for this entity and generate mesh data
4689                 numvertices = model->surfmesh.num_vertices;
4690                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4691                 if (wantnormals)
4692                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                 if (wanttangents)
4694                 {
4695                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4696                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4697                 }
4698                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4699                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4700         }
4701         return true;
4702 }
4703
4704 void R_AnimCache_CacheVisibleEntities(void)
4705 {
4706         int i;
4707         qboolean wantnormals = true;
4708         qboolean wanttangents = !r_showsurfaces.integer;
4709
4710         switch(vid.renderpath)
4711         {
4712         case RENDERPATH_GL20:
4713         case RENDERPATH_D3D9:
4714         case RENDERPATH_D3D10:
4715         case RENDERPATH_D3D11:
4716         case RENDERPATH_GLES2:
4717                 break;
4718         case RENDERPATH_GL11:
4719         case RENDERPATH_GL13:
4720         case RENDERPATH_GLES1:
4721                 wanttangents = false;
4722                 break;
4723         case RENDERPATH_SOFT:
4724                 break;
4725         }
4726
4727         if (r_shownormals.integer)
4728                 wanttangents = wantnormals = true;
4729
4730         // TODO: thread this
4731         // NOTE: R_PrepareRTLights() also caches entities
4732
4733         for (i = 0;i < r_refdef.scene.numentities;i++)
4734                 if (r_refdef.viewcache.entityvisible[i])
4735                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4736 }
4737
4738 //==================================================================================
4739
4740 extern cvar_t r_overheadsprites_pushback;
4741
4742 static void R_View_UpdateEntityLighting (void)
4743 {
4744         int i;
4745         entity_render_t *ent;
4746         vec3_t tempdiffusenormal, avg;
4747         vec_t f, fa, fd, fdd;
4748         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4749
4750         for (i = 0;i < r_refdef.scene.numentities;i++)
4751         {
4752                 ent = r_refdef.scene.entities[i];
4753
4754                 // skip unseen models
4755                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4756                         continue;
4757
4758                 // skip bsp models
4759                 if (ent->model && ent->model->brush.num_leafs)
4760                 {
4761                         // TODO: use modellight for r_ambient settings on world?
4762                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4763                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4764                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4765                         continue;
4766                 }
4767
4768                 // fetch the lighting from the worldmodel data
4769                 VectorClear(ent->modellight_ambient);
4770                 VectorClear(ent->modellight_diffuse);
4771                 VectorClear(tempdiffusenormal);
4772                 if (ent->flags & RENDER_LIGHT)
4773                 {
4774                         vec3_t org;
4775                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4776
4777                         // complete lightning for lit sprites
4778                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4779                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4780                         {
4781                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4782                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4783                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4784                         }
4785                         else
4786                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4787
4788                         if(ent->flags & RENDER_EQUALIZE)
4789                         {
4790                                 // first fix up ambient lighting...
4791                                 if(r_equalize_entities_minambient.value > 0)
4792                                 {
4793                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794                                         if(fd > 0)
4795                                         {
4796                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4797                                                 if(fa < r_equalize_entities_minambient.value * fd)
4798                                                 {
4799                                                         // solve:
4800                                                         //   fa'/fd' = minambient
4801                                                         //   fa'+0.25*fd' = fa+0.25*fd
4802                                                         //   ...
4803                                                         //   fa' = fd' * minambient
4804                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4805                                                         //   ...
4806                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4807                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4808                                                         //   ...
4809                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4810                                                         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
4811                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4812                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4813                                                 }
4814                                         }
4815                                 }
4816
4817                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4818                                 {
4819                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4820                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                         f = fa + 0.25 * fd;
4822                                         if(f > 0)
4823                                         {
4824                                                 // adjust brightness and saturation to target
4825                                                 avg[0] = avg[1] = avg[2] = fa / f;
4826                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4827                                                 avg[0] = avg[1] = avg[2] = fd / f;
4828                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4829                                         }
4830                                 }
4831                         }
4832                 }
4833                 else // highly rare
4834                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4835
4836                 // move the light direction into modelspace coordinates for lighting code
4837                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4838                 if(VectorLength2(ent->modellight_lightdir) == 0)
4839                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4840                 VectorNormalize(ent->modellight_lightdir);
4841         }
4842 }
4843
4844 #define MAX_LINEOFSIGHTTRACES 64
4845
4846 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4847 {
4848         int i;
4849         vec3_t boxmins, boxmaxs;
4850         vec3_t start;
4851         vec3_t end;
4852         dp_model_t *model = r_refdef.scene.worldmodel;
4853
4854         if (!model || !model->brush.TraceLineOfSight)
4855                 return true;
4856
4857         // expand the box a little
4858         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4859         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4860         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4861         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4862         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4863         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4864
4865         // return true if eye is inside enlarged box
4866         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4867                 return true;
4868
4869         // try center
4870         VectorCopy(eye, start);
4871         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4872         if (model->brush.TraceLineOfSight(model, start, end))
4873                 return true;
4874
4875         // try various random positions
4876         for (i = 0;i < numsamples;i++)
4877         {
4878                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4879                 if (model->brush.TraceLineOfSight(model, start, end))
4880                         return true;
4881         }
4882
4883         return false;
4884 }
4885
4886
4887 static void R_View_UpdateEntityVisible (void)
4888 {
4889         int i;
4890         int renderimask;
4891         int samples;
4892         entity_render_t *ent;
4893
4894         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4895                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4896                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4897                 :                                                          RENDER_EXTERIORMODEL;
4898         if (!r_drawviewmodel.integer)
4899                 renderimask |= RENDER_VIEWMODEL;
4900         if (!r_drawexteriormodel.integer)
4901                 renderimask |= RENDER_EXTERIORMODEL;
4902         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4903         {
4904                 // worldmodel can check visibility
4905                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4906                 for (i = 0;i < r_refdef.scene.numentities;i++)
4907                 {
4908                         ent = r_refdef.scene.entities[i];
4909                         if (!(ent->flags & renderimask))
4910                         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)))
4911                         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))
4912                                 r_refdef.viewcache.entityvisible[i] = true;
4913                 }
4914         }
4915         else
4916         {
4917                 // no worldmodel or it can't check visibility
4918                 for (i = 0;i < r_refdef.scene.numentities;i++)
4919                 {
4920                         ent = r_refdef.scene.entities[i];
4921                         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));
4922                 }
4923         }
4924         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4925                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4926         {
4927                 for (i = 0;i < r_refdef.scene.numentities;i++)
4928                 {
4929                         if (!r_refdef.viewcache.entityvisible[i])
4930                                 continue;
4931                         ent = r_refdef.scene.entities[i];
4932                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4933                         {
4934                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4935                                 if (samples < 0)
4936                                         continue; // temp entities do pvs only
4937                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4938                                         ent->last_trace_visibility = realtime;
4939                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4940                                         r_refdef.viewcache.entityvisible[i] = 0;
4941                         }
4942                 }
4943         }
4944 }
4945
4946 /// only used if skyrendermasked, and normally returns false
4947 int R_DrawBrushModelsSky (void)
4948 {
4949         int i, sky;
4950         entity_render_t *ent;
4951
4952         sky = false;
4953         for (i = 0;i < r_refdef.scene.numentities;i++)
4954         {
4955                 if (!r_refdef.viewcache.entityvisible[i])
4956                         continue;
4957                 ent = r_refdef.scene.entities[i];
4958                 if (!ent->model || !ent->model->DrawSky)
4959                         continue;
4960                 ent->model->DrawSky(ent);
4961                 sky = true;
4962         }
4963         return sky;
4964 }
4965
4966 static void R_DrawNoModel(entity_render_t *ent);
4967 static void R_DrawModels(void)
4968 {
4969         int i;
4970         entity_render_t *ent;
4971
4972         for (i = 0;i < r_refdef.scene.numentities;i++)
4973         {
4974                 if (!r_refdef.viewcache.entityvisible[i])
4975                         continue;
4976                 ent = r_refdef.scene.entities[i];
4977                 r_refdef.stats.entities++;
4978                 /*
4979                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4980                 {
4981                         vec3_t f, l, u, o;
4982                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4983                         Con_Printf("R_DrawModels\n");
4984                         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]);
4985                         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);
4986                         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);
4987                 }
4988                 */
4989                 if (ent->model && ent->model->Draw != NULL)
4990                         ent->model->Draw(ent);
4991                 else
4992                         R_DrawNoModel(ent);
4993         }
4994 }
4995
4996 static void R_DrawModelsDepth(void)
4997 {
4998         int i;
4999         entity_render_t *ent;
5000
5001         for (i = 0;i < r_refdef.scene.numentities;i++)
5002         {
5003                 if (!r_refdef.viewcache.entityvisible[i])
5004                         continue;
5005                 ent = r_refdef.scene.entities[i];
5006                 if (ent->model && ent->model->DrawDepth != NULL)
5007                         ent->model->DrawDepth(ent);
5008         }
5009 }
5010
5011 static void R_DrawModelsDebug(void)
5012 {
5013         int i;
5014         entity_render_t *ent;
5015
5016         for (i = 0;i < r_refdef.scene.numentities;i++)
5017         {
5018                 if (!r_refdef.viewcache.entityvisible[i])
5019                         continue;
5020                 ent = r_refdef.scene.entities[i];
5021                 if (ent->model && ent->model->DrawDebug != NULL)
5022                         ent->model->DrawDebug(ent);
5023         }
5024 }
5025
5026 static void R_DrawModelsAddWaterPlanes(void)
5027 {
5028         int i;
5029         entity_render_t *ent;
5030
5031         for (i = 0;i < r_refdef.scene.numentities;i++)
5032         {
5033                 if (!r_refdef.viewcache.entityvisible[i])
5034                         continue;
5035                 ent = r_refdef.scene.entities[i];
5036                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5037                         ent->model->DrawAddWaterPlanes(ent);
5038         }
5039 }
5040
5041 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5042 {
5043         if (r_hdr_irisadaptation.integer)
5044         {
5045                 vec3_t ambient;
5046                 vec3_t diffuse;
5047                 vec3_t diffusenormal;
5048                 vec_t brightness;
5049                 vec_t goal;
5050                 vec_t current;
5051                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5052                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5053                 brightness = max(0.0000001f, brightness);
5054                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5055                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5056                 current = r_hdr_irisadaptation_value.value;
5057                 if (current < goal)
5058                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5059                 else if (current > goal)
5060                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5061                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5062                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5063         }
5064         else if (r_hdr_irisadaptation_value.value != 1.0f)
5065                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5066 }
5067
5068 static void R_View_SetFrustum(const int *scissor)
5069 {
5070         int i;
5071         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5072         vec3_t forward, left, up, origin, v;
5073
5074         if(scissor)
5075         {
5076                 // flipped x coordinates (because x points left here)
5077                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5078                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5079
5080                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5081                 switch(vid.renderpath)
5082                 {
5083                         case RENDERPATH_D3D9:
5084                         case RENDERPATH_D3D10:
5085                         case RENDERPATH_D3D11:
5086                                 // non-flipped y coordinates
5087                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5088                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5089                                 break;
5090                         case RENDERPATH_SOFT:
5091                         case RENDERPATH_GL11:
5092                         case RENDERPATH_GL13:
5093                         case RENDERPATH_GL20:
5094                         case RENDERPATH_GLES1:
5095                         case RENDERPATH_GLES2:
5096                                 // non-flipped y coordinates
5097                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5098                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5099                                 break;
5100                 }
5101         }
5102
5103         // we can't trust r_refdef.view.forward and friends in reflected scenes
5104         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5105
5106 #if 0
5107         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5108         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5109         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5110         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5111         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5112         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5113         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5114         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5115         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5116         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5117         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5118         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5119 #endif
5120
5121 #if 0
5122         zNear = r_refdef.nearclip;
5123         nudge = 1.0 - 1.0 / (1<<23);
5124         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5125         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5126         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5127         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5128         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5129         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5130         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5131         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5132 #endif
5133
5134
5135
5136 #if 0
5137         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5138         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5139         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5140         r_refdef.view.frustum[0].dist = m[15] - m[12];
5141
5142         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5143         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5144         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5145         r_refdef.view.frustum[1].dist = m[15] + m[12];
5146
5147         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5148         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5149         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5150         r_refdef.view.frustum[2].dist = m[15] - m[13];
5151
5152         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5153         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5154         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5155         r_refdef.view.frustum[3].dist = m[15] + m[13];
5156
5157         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5158         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5159         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5160         r_refdef.view.frustum[4].dist = m[15] - m[14];
5161
5162         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5163         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5164         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5165         r_refdef.view.frustum[5].dist = m[15] + m[14];
5166 #endif
5167
5168         if (r_refdef.view.useperspective)
5169         {
5170                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5171                 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]);
5172                 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]);
5173                 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]);
5174                 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]);
5175
5176                 // then the normals from the corners relative to origin
5177                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5178                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5179                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5180                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5181
5182                 // in a NORMAL view, forward cross left == up
5183                 // in a REFLECTED view, forward cross left == down
5184                 // so our cross products above need to be adjusted for a left handed coordinate system
5185                 CrossProduct(forward, left, v);
5186                 if(DotProduct(v, up) < 0)
5187                 {
5188                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5189                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5190                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5191                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5192                 }
5193
5194                 // Leaving those out was a mistake, those were in the old code, and they
5195                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5196                 // I couldn't reproduce it after adding those normalizations. --blub
5197                 VectorNormalize(r_refdef.view.frustum[0].normal);
5198                 VectorNormalize(r_refdef.view.frustum[1].normal);
5199                 VectorNormalize(r_refdef.view.frustum[2].normal);
5200                 VectorNormalize(r_refdef.view.frustum[3].normal);
5201
5202                 // make the corners absolute
5203                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5204                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5205                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5206                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5207
5208                 // one more normal
5209                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5210
5211                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5212                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5213                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5214                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5215                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5216         }
5217         else
5218         {
5219                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5220                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5221                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5222                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5223                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5224                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5225                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5226                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5227                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5228                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5229         }
5230         r_refdef.view.numfrustumplanes = 5;
5231
5232         if (r_refdef.view.useclipplane)
5233         {
5234                 r_refdef.view.numfrustumplanes = 6;
5235                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5236         }
5237
5238         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5239                 PlaneClassify(r_refdef.view.frustum + i);
5240
5241         // LordHavoc: note to all quake engine coders, Quake had a special case
5242         // for 90 degrees which assumed a square view (wrong), so I removed it,
5243         // Quake2 has it disabled as well.
5244
5245         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5246         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5247         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5248         //PlaneClassify(&frustum[0]);
5249
5250         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5251         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5252         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5253         //PlaneClassify(&frustum[1]);
5254
5255         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5256         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5257         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5258         //PlaneClassify(&frustum[2]);
5259
5260         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5261         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5262         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5263         //PlaneClassify(&frustum[3]);
5264
5265         // nearclip plane
5266         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5267         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5268         //PlaneClassify(&frustum[4]);
5269 }
5270
5271 void R_View_UpdateWithScissor(const int *myscissor)
5272 {
5273         R_Main_ResizeViewCache();
5274         R_View_SetFrustum(myscissor);
5275         R_View_WorldVisibility(r_refdef.view.useclipplane);
5276         R_View_UpdateEntityVisible();
5277         R_View_UpdateEntityLighting();
5278 }
5279
5280 void R_View_Update(void)
5281 {
5282         R_Main_ResizeViewCache();
5283         R_View_SetFrustum(NULL);
5284         R_View_WorldVisibility(r_refdef.view.useclipplane);
5285         R_View_UpdateEntityVisible();
5286         R_View_UpdateEntityLighting();
5287 }
5288
5289 float viewscalefpsadjusted = 1.0f;
5290
5291 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5292 {
5293         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5294         scale = bound(0.03125f, scale, 1.0f);
5295         *outwidth = (int)ceil(width * scale);
5296         *outheight = (int)ceil(height * scale);
5297 }
5298
5299 void R_Mesh_SetMainRenderTargets(void)
5300 {
5301         if (r_bloomstate.fbo_framebuffer)
5302                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5303         else
5304                 R_Mesh_ResetRenderTargets();
5305 }
5306
5307 void R_SetupView(qboolean allowwaterclippingplane)
5308 {
5309         const float *customclipplane = NULL;
5310         float plane[4];
5311         int scaledwidth, scaledheight;
5312         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5313         {
5314                 // LordHavoc: couldn't figure out how to make this approach the
5315                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5316                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5317                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5318                         dist = r_refdef.view.clipplane.dist;
5319                 plane[0] = r_refdef.view.clipplane.normal[0];
5320                 plane[1] = r_refdef.view.clipplane.normal[1];
5321                 plane[2] = r_refdef.view.clipplane.normal[2];
5322                 plane[3] = -dist;
5323                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5324         }
5325
5326         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5327         if (!r_refdef.view.useperspective)
5328                 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);
5329         else if (vid.stencil && r_useinfinitefarclip.integer)
5330                 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);
5331         else
5332                 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);
5333         R_Mesh_SetMainRenderTargets();
5334         R_SetViewport(&r_refdef.view.viewport);
5335         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5336         {
5337                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5338                 float screenplane[4];
5339                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5340                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5341                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5342                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5343                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5344         }
5345 }
5346
5347 void R_EntityMatrix(const matrix4x4_t *matrix)
5348 {
5349         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5350         {
5351                 gl_modelmatrixchanged = false;
5352                 gl_modelmatrix = *matrix;
5353                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5354                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5355                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5356                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5357                 CHECKGLERROR
5358                 switch(vid.renderpath)
5359                 {
5360                 case RENDERPATH_D3D9:
5361 #ifdef SUPPORTD3D
5362                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5363                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5364 #endif
5365                         break;
5366                 case RENDERPATH_D3D10:
5367                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5368                         break;
5369                 case RENDERPATH_D3D11:
5370                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5371                         break;
5372                 case RENDERPATH_GL11:
5373                 case RENDERPATH_GL13:
5374                 case RENDERPATH_GLES1:
5375                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5376                         break;
5377                 case RENDERPATH_SOFT:
5378                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5379                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5380                         break;
5381                 case RENDERPATH_GL20:
5382                 case RENDERPATH_GLES2:
5383                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5384                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5385                         break;
5386                 }
5387         }
5388 }
5389
5390 void R_ResetViewRendering2D(void)
5391 {
5392         r_viewport_t viewport;
5393         DrawQ_Finish();
5394
5395         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5396         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);
5397         R_Mesh_ResetRenderTargets();
5398         R_SetViewport(&viewport);
5399         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5400         GL_Color(1, 1, 1, 1);
5401         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5402         GL_BlendFunc(GL_ONE, GL_ZERO);
5403         GL_ScissorTest(false);
5404         GL_DepthMask(false);
5405         GL_DepthRange(0, 1);
5406         GL_DepthTest(false);
5407         GL_DepthFunc(GL_LEQUAL);
5408         R_EntityMatrix(&identitymatrix);
5409         R_Mesh_ResetTextureState();
5410         GL_PolygonOffset(0, 0);
5411         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5412         switch(vid.renderpath)
5413         {
5414         case RENDERPATH_GL11:
5415         case RENDERPATH_GL13:
5416         case RENDERPATH_GL20:
5417         case RENDERPATH_GLES1:
5418         case RENDERPATH_GLES2:
5419                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5420                 break;
5421         case RENDERPATH_D3D9:
5422         case RENDERPATH_D3D10:
5423         case RENDERPATH_D3D11:
5424         case RENDERPATH_SOFT:
5425                 break;
5426         }
5427         GL_CullFace(GL_NONE);
5428 }
5429
5430 void R_ResetViewRendering3D(void)
5431 {
5432         DrawQ_Finish();
5433
5434         R_SetupView(true);
5435         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5436         GL_Color(1, 1, 1, 1);
5437         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5438         GL_BlendFunc(GL_ONE, GL_ZERO);
5439         GL_ScissorTest(true);
5440         GL_DepthMask(true);
5441         GL_DepthRange(0, 1);
5442         GL_DepthTest(true);
5443         GL_DepthFunc(GL_LEQUAL);
5444         R_EntityMatrix(&identitymatrix);
5445         R_Mesh_ResetTextureState();
5446         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5447         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5448         switch(vid.renderpath)
5449         {
5450         case RENDERPATH_GL11:
5451         case RENDERPATH_GL13:
5452         case RENDERPATH_GL20:
5453         case RENDERPATH_GLES1:
5454         case RENDERPATH_GLES2:
5455                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5456                 break;
5457         case RENDERPATH_D3D9:
5458         case RENDERPATH_D3D10:
5459         case RENDERPATH_D3D11:
5460         case RENDERPATH_SOFT:
5461                 break;
5462         }
5463         GL_CullFace(r_refdef.view.cullface_back);
5464 }
5465
5466 /*
5467 ================
5468 R_RenderView_UpdateViewVectors
5469 ================
5470 */
5471 static void R_RenderView_UpdateViewVectors(void)
5472 {
5473         // break apart the view matrix into vectors for various purposes
5474         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5475         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5476         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5477         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5478         // make an inverted copy of the view matrix for tracking sprites
5479         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5480 }
5481
5482 void R_RenderScene(void);
5483 void R_RenderWaterPlanes(void);
5484
5485 static void R_Water_StartFrame(void)
5486 {
5487         int i;
5488         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5489         r_waterstate_waterplane_t *p;
5490
5491         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5492                 return;
5493
5494         switch(vid.renderpath)
5495         {
5496         case RENDERPATH_GL20:
5497         case RENDERPATH_D3D9:
5498         case RENDERPATH_D3D10:
5499         case RENDERPATH_D3D11:
5500         case RENDERPATH_SOFT:
5501         case RENDERPATH_GLES2:
5502                 break;
5503         case RENDERPATH_GL11:
5504         case RENDERPATH_GL13:
5505         case RENDERPATH_GLES1:
5506                 return;
5507         }
5508
5509         // set waterwidth and waterheight to the water resolution that will be
5510         // used (often less than the screen resolution for faster rendering)
5511         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5512
5513         // calculate desired texture sizes
5514         // can't use water if the card does not support the texture size
5515         if (!r_water.integer || r_showsurfaces.integer)
5516                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5517         else if (vid.support.arb_texture_non_power_of_two)
5518         {
5519                 texturewidth = waterwidth;
5520                 textureheight = waterheight;
5521                 camerawidth = waterwidth;
5522                 cameraheight = waterheight;
5523         }
5524         else
5525         {
5526                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5527                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5528                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5529                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5530         }
5531
5532         // allocate textures as needed
5533         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5534         {
5535                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5536                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5537                 {
5538                         if (p->texture_refraction)
5539                                 R_FreeTexture(p->texture_refraction);
5540                         p->texture_refraction = NULL;
5541                         if (p->texture_reflection)
5542                                 R_FreeTexture(p->texture_reflection);
5543                         p->texture_reflection = NULL;
5544                         if (p->texture_camera)
5545                                 R_FreeTexture(p->texture_camera);
5546                         p->texture_camera = NULL;
5547                 }
5548                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5549                 r_waterstate.texturewidth = texturewidth;
5550                 r_waterstate.textureheight = textureheight;
5551                 r_waterstate.camerawidth = camerawidth;
5552                 r_waterstate.cameraheight = cameraheight;
5553         }
5554
5555         if (r_waterstate.texturewidth)
5556         {
5557                 int scaledwidth, scaledheight;
5558
5559                 r_waterstate.enabled = true;
5560
5561                 // when doing a reduced render (HDR) we want to use a smaller area
5562                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5563                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5564                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5565
5566                 // set up variables that will be used in shader setup
5567                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5568                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5569                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5570                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5571         }
5572
5573         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5574         r_waterstate.numwaterplanes = 0;
5575 }
5576
5577 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5578 {
5579         int triangleindex, planeindex;
5580         const int *e;
5581         vec3_t vert[3];
5582         vec3_t normal;
5583         vec3_t center;
5584         mplane_t plane;
5585         r_waterstate_waterplane_t *p;
5586         texture_t *t = R_GetCurrentTexture(surface->texture);
5587
5588         // just use the first triangle with a valid normal for any decisions
5589         VectorClear(normal);
5590         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5591         {
5592                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5593                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5594                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5595                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5596                 if (VectorLength2(normal) >= 0.001)
5597                         break;
5598         }
5599
5600         VectorCopy(normal, plane.normal);
5601         VectorNormalize(plane.normal);
5602         plane.dist = DotProduct(vert[0], plane.normal);
5603         PlaneClassify(&plane);
5604         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5605         {
5606                 // skip backfaces (except if nocullface is set)
5607                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5608                         return;
5609                 VectorNegate(plane.normal, plane.normal);
5610                 plane.dist *= -1;
5611                 PlaneClassify(&plane);
5612         }
5613
5614
5615         // find a matching plane if there is one
5616         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5617                 if(p->camera_entity == t->camera_entity)
5618                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5619                                 break;
5620         if (planeindex >= r_waterstate.maxwaterplanes)
5621                 return; // nothing we can do, out of planes
5622
5623         // if this triangle does not fit any known plane rendered this frame, add one
5624         if (planeindex >= r_waterstate.numwaterplanes)
5625         {
5626                 // store the new plane
5627                 r_waterstate.numwaterplanes++;
5628                 p->plane = plane;
5629                 // clear materialflags and pvs
5630                 p->materialflags = 0;
5631                 p->pvsvalid = false;
5632                 p->camera_entity = t->camera_entity;
5633                 VectorCopy(surface->mins, p->mins);
5634                 VectorCopy(surface->maxs, p->maxs);
5635         }
5636         else
5637         {
5638                 // merge mins/maxs
5639                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5640                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5641                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5642                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5643                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5644                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5645         }
5646         // merge this surface's materialflags into the waterplane
5647         p->materialflags |= t->currentmaterialflags;
5648         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5649         {
5650                 // merge this surface's PVS into the waterplane
5651                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5652                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5653                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5654                 {
5655                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5656                         p->pvsvalid = true;
5657                 }
5658         }
5659 }
5660
5661 extern cvar_t r_drawparticles;
5662 extern cvar_t r_drawdecals;
5663
5664 static void R_Water_ProcessPlanes(void)
5665 {
5666         int myscissor[4];
5667         r_refdef_view_t originalview;
5668         r_refdef_view_t myview;
5669         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;
5670         r_waterstate_waterplane_t *p;
5671         vec3_t visorigin;
5672
5673         originalview = r_refdef.view;
5674
5675         // lowquality hack, temporarily shut down some cvars and restore afterwards
5676         qualityreduction = r_water_lowquality.integer;
5677         if (qualityreduction > 0)
5678         {
5679                 if (qualityreduction >= 1)
5680                 {
5681                         old_r_shadows = r_shadows.integer;
5682                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5683                         old_r_dlight = r_shadow_realtime_dlight.integer;
5684                         Cvar_SetValueQuick(&r_shadows, 0);
5685                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5686                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5687                 }
5688                 if (qualityreduction >= 2)
5689                 {
5690                         old_r_dynamic = r_dynamic.integer;
5691                         old_r_particles = r_drawparticles.integer;
5692                         old_r_decals = r_drawdecals.integer;
5693                         Cvar_SetValueQuick(&r_dynamic, 0);
5694                         Cvar_SetValueQuick(&r_drawparticles, 0);
5695                         Cvar_SetValueQuick(&r_drawdecals, 0);
5696                 }
5697         }
5698
5699         // make sure enough textures are allocated
5700         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5701         {
5702                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5703                 {
5704                         if (!p->texture_refraction)
5705                                 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);
5706                         if (!p->texture_refraction)
5707                                 goto error;
5708                 }
5709                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5710                 {
5711                         if (!p->texture_camera)
5712                                 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);
5713                         if (!p->texture_camera)
5714                                 goto error;
5715                 }
5716
5717                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5718                 {
5719                         if (!p->texture_reflection)
5720                                 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);
5721                         if (!p->texture_reflection)
5722                                 goto error;
5723                 }
5724         }
5725
5726         // render views
5727         r_refdef.view = originalview;
5728         r_refdef.view.showdebug = false;
5729         r_refdef.view.width = r_waterstate.waterwidth;
5730         r_refdef.view.height = r_waterstate.waterheight;
5731         r_refdef.view.useclipplane = true;
5732         myview = r_refdef.view;
5733         r_waterstate.renderingscene = true;
5734         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5735         {
5736                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5737                 {
5738                         r_refdef.view = myview;
5739                         if(r_water_scissormode.integer)
5740                         {
5741                                 R_SetupView(true);
5742                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5743                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5744                         }
5745
5746                         // render reflected scene and copy into texture
5747                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5748                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5749                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5750                         r_refdef.view.clipplane = p->plane;
5751                         // reverse the cullface settings for this render
5752                         r_refdef.view.cullface_front = GL_FRONT;
5753                         r_refdef.view.cullface_back = GL_BACK;
5754                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5755                         {
5756                                 r_refdef.view.usecustompvs = true;
5757                                 if (p->pvsvalid)
5758                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5759                                 else
5760                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5761                         }
5762
5763                         R_ResetViewRendering3D();
5764                         R_ClearScreen(r_refdef.fogenabled);
5765                         if(r_water_scissormode.integer & 2)
5766                                 R_View_UpdateWithScissor(myscissor);
5767                         else
5768                                 R_View_Update();
5769                         if(r_water_scissormode.integer & 1)
5770                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5771                         R_RenderScene();
5772
5773                         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);
5774                 }
5775
5776                 // render the normal view scene and copy into texture
5777                 // (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)
5778                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5779                 {
5780                         r_refdef.view = myview;
5781                         if(r_water_scissormode.integer)
5782                         {
5783                                 R_SetupView(true);
5784                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5785                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5786                         }
5787
5788                         r_waterstate.renderingrefraction = true;
5789
5790                         r_refdef.view.clipplane = p->plane;
5791                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5792                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5793
5794                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5795                         {
5796                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5797                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5798                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5799                                 R_RenderView_UpdateViewVectors();
5800                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5801                                 {
5802                                         r_refdef.view.usecustompvs = true;
5803                                         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);
5804                                 }
5805                         }
5806
5807                         PlaneClassify(&r_refdef.view.clipplane);
5808
5809                         R_ResetViewRendering3D();
5810                         R_ClearScreen(r_refdef.fogenabled);
5811                         if(r_water_scissormode.integer & 2)
5812                                 R_View_UpdateWithScissor(myscissor);
5813                         else
5814                                 R_View_Update();
5815                         if(r_water_scissormode.integer & 1)
5816                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5817                         R_RenderScene();
5818
5819                         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);
5820                         r_waterstate.renderingrefraction = false;
5821                 }
5822                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5823                 {
5824                         r_refdef.view = myview;
5825
5826                         r_refdef.view.clipplane = p->plane;
5827                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5828                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5829
5830                         r_refdef.view.width = r_waterstate.camerawidth;
5831                         r_refdef.view.height = r_waterstate.cameraheight;
5832                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5833                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5834
5835                         if(p->camera_entity)
5836                         {
5837                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5838                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5839                         }
5840
5841                         // note: all of the view is used for displaying... so
5842                         // there is no use in scissoring
5843
5844                         // reverse the cullface settings for this render
5845                         r_refdef.view.cullface_front = GL_FRONT;
5846                         r_refdef.view.cullface_back = GL_BACK;
5847                         // also reverse the view matrix
5848                         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
5849                         R_RenderView_UpdateViewVectors();
5850                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5851                         {
5852                                 r_refdef.view.usecustompvs = true;
5853                                 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);
5854                         }
5855                         
5856                         // camera needs no clipplane
5857                         r_refdef.view.useclipplane = false;
5858
5859                         PlaneClassify(&r_refdef.view.clipplane);
5860
5861                         R_ResetViewRendering3D();
5862                         R_ClearScreen(r_refdef.fogenabled);
5863                         R_View_Update();
5864                         R_RenderScene();
5865
5866                         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);
5867                         r_waterstate.renderingrefraction = false;
5868                 }
5869
5870         }
5871         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5872         r_waterstate.renderingscene = false;
5873         r_refdef.view = originalview;
5874         R_ResetViewRendering3D();
5875         R_ClearScreen(r_refdef.fogenabled);
5876         R_View_Update();
5877         goto finish;
5878 error:
5879         r_refdef.view = originalview;
5880         r_waterstate.renderingscene = false;
5881         Cvar_SetValueQuick(&r_water, 0);
5882         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5883 finish:
5884         // lowquality hack, restore cvars
5885         if (qualityreduction > 0)
5886         {
5887                 if (qualityreduction >= 1)
5888                 {
5889                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5890                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5891                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5892                 }
5893                 if (qualityreduction >= 2)
5894                 {
5895                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5896                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5897                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5898                 }
5899         }
5900 }
5901
5902 void R_Bloom_StartFrame(void)
5903 {
5904         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5905         int viewwidth, viewheight;
5906         textype_t textype;
5907
5908         if (r_viewscale_fpsscaling.integer)
5909         {
5910                 double actualframetime;
5911                 double targetframetime;
5912                 double adjust;
5913                 actualframetime = r_refdef.lastdrawscreentime;
5914                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5915                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5916                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5917                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5918                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5919                 viewscalefpsadjusted += adjust;
5920                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5921         }
5922         else
5923                 viewscalefpsadjusted = 1.0f;
5924
5925         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5926
5927         switch(vid.renderpath)
5928         {
5929         case RENDERPATH_GL20:
5930         case RENDERPATH_D3D9:
5931         case RENDERPATH_D3D10:
5932         case RENDERPATH_D3D11:
5933         case RENDERPATH_SOFT:
5934         case RENDERPATH_GLES2:
5935                 break;
5936         case RENDERPATH_GL11:
5937         case RENDERPATH_GL13:
5938         case RENDERPATH_GLES1:
5939                 return;
5940         }
5941
5942         // set bloomwidth and bloomheight to the bloom resolution that will be
5943         // used (often less than the screen resolution for faster rendering)
5944         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5945         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5946         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5947         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5948         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5949
5950         // calculate desired texture sizes
5951         if (vid.support.arb_texture_non_power_of_two)
5952         {
5953                 screentexturewidth = vid.width;
5954                 screentextureheight = vid.height;
5955                 bloomtexturewidth = r_bloomstate.bloomwidth;
5956                 bloomtextureheight = r_bloomstate.bloomheight;
5957         }
5958         else
5959         {
5960                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5961                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5962                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5963                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5964         }
5965
5966         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))
5967         {
5968                 Cvar_SetValueQuick(&r_hdr, 0);
5969                 Cvar_SetValueQuick(&r_bloom, 0);
5970                 Cvar_SetValueQuick(&r_motionblur, 0);
5971                 Cvar_SetValueQuick(&r_damageblur, 0);
5972         }
5973
5974         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)
5975                 screentexturewidth = screentextureheight = 0;
5976         if (!r_hdr.integer && !r_bloom.integer)
5977                 bloomtexturewidth = bloomtextureheight = 0;
5978
5979         textype = TEXTYPE_COLORBUFFER;
5980         switch (vid.renderpath)
5981         {
5982         case RENDERPATH_GL20:
5983         case RENDERPATH_GLES2:
5984                 if (vid.support.ext_framebuffer_object)
5985                 {
5986                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5987                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5988                 }
5989                 break;
5990         case RENDERPATH_GL11:
5991         case RENDERPATH_GL13:
5992         case RENDERPATH_GLES1:
5993         case RENDERPATH_D3D9:
5994         case RENDERPATH_D3D10:
5995         case RENDERPATH_D3D11:
5996         case RENDERPATH_SOFT:
5997                 break;
5998         }
5999
6000         // allocate textures as needed
6001         if (r_bloomstate.screentexturewidth != screentexturewidth
6002          || r_bloomstate.screentextureheight != screentextureheight
6003          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6004          || r_bloomstate.bloomtextureheight != bloomtextureheight
6005          || r_bloomstate.texturetype != textype
6006          || r_bloomstate.viewfbo != r_viewfbo.integer)
6007         {
6008                 if (r_bloomstate.texture_bloom)
6009                         R_FreeTexture(r_bloomstate.texture_bloom);
6010                 r_bloomstate.texture_bloom = NULL;
6011                 if (r_bloomstate.texture_screen)
6012                         R_FreeTexture(r_bloomstate.texture_screen);
6013                 r_bloomstate.texture_screen = NULL;
6014                 if (r_bloomstate.fbo_framebuffer)
6015                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6016                 r_bloomstate.fbo_framebuffer = 0;
6017                 if (r_bloomstate.texture_framebuffercolor)
6018                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6019                 r_bloomstate.texture_framebuffercolor = NULL;
6020                 if (r_bloomstate.texture_framebufferdepth)
6021                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6022                 r_bloomstate.texture_framebufferdepth = NULL;
6023                 r_bloomstate.screentexturewidth = screentexturewidth;
6024                 r_bloomstate.screentextureheight = screentextureheight;
6025                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6026                         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);
6027                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6028                 {
6029                         // FIXME: choose depth bits based on a cvar
6030                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6031                         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);
6032                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6033                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6034 #ifndef USE_GLES2
6035                         // render depth into one texture and normalmap into the other
6036                         if (qglDrawBuffer)
6037                         {
6038                                 int status;
6039                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6040                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6041                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6042                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6043                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6044                         }
6045 #endif
6046                 }
6047                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6048                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6049                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6050                         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);
6051                 r_bloomstate.viewfbo = r_viewfbo.integer;
6052                 r_bloomstate.texturetype = textype;
6053         }
6054
6055         // when doing a reduced render (HDR) we want to use a smaller area
6056         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6057         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6058         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6059         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6060         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6061
6062         // set up a texcoord array for the full resolution screen image
6063         // (we have to keep this around to copy back during final render)
6064         r_bloomstate.screentexcoord2f[0] = 0;
6065         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6066         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6067         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6068         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6069         r_bloomstate.screentexcoord2f[5] = 0;
6070         r_bloomstate.screentexcoord2f[6] = 0;
6071         r_bloomstate.screentexcoord2f[7] = 0;
6072
6073         // set up a texcoord array for the reduced resolution bloom image
6074         // (which will be additive blended over the screen image)
6075         r_bloomstate.bloomtexcoord2f[0] = 0;
6076         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6077         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6078         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6079         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6080         r_bloomstate.bloomtexcoord2f[5] = 0;
6081         r_bloomstate.bloomtexcoord2f[6] = 0;
6082         r_bloomstate.bloomtexcoord2f[7] = 0;
6083
6084         switch(vid.renderpath)
6085         {
6086         case RENDERPATH_GL11:
6087         case RENDERPATH_GL13:
6088         case RENDERPATH_GL20:
6089         case RENDERPATH_SOFT:
6090         case RENDERPATH_GLES1:
6091         case RENDERPATH_GLES2:
6092                 break;
6093         case RENDERPATH_D3D9:
6094         case RENDERPATH_D3D10:
6095         case RENDERPATH_D3D11:
6096                 {
6097                         int i;
6098                         for (i = 0;i < 4;i++)
6099                         {
6100                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6101                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6102                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6103                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6104                         }
6105                 }
6106                 break;
6107         }
6108
6109         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6110         {
6111                 r_bloomstate.enabled = true;
6112                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6113         }
6114
6115         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);
6116
6117         if (r_bloomstate.fbo_framebuffer)
6118                 r_refdef.view.clear = true;
6119 }
6120
6121 void R_Bloom_CopyBloomTexture(float colorscale)
6122 {
6123         r_refdef.stats.bloom++;
6124
6125         // scale down screen texture to the bloom texture size
6126         CHECKGLERROR
6127         R_Mesh_SetMainRenderTargets();
6128         R_SetViewport(&r_bloomstate.viewport);
6129         GL_BlendFunc(GL_ONE, GL_ZERO);
6130         GL_Color(colorscale, colorscale, colorscale, 1);
6131         // 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...
6132         switch(vid.renderpath)
6133         {
6134         case RENDERPATH_GL11:
6135         case RENDERPATH_GL13:
6136         case RENDERPATH_GL20:
6137         case RENDERPATH_GLES1:
6138         case RENDERPATH_GLES2:
6139         case RENDERPATH_SOFT:
6140                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6141                 break;
6142         case RENDERPATH_D3D9:
6143         case RENDERPATH_D3D10:
6144         case RENDERPATH_D3D11:
6145                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6146                 break;
6147         }
6148         // TODO: do boxfilter scale-down in shader?
6149         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6150         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6151         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6152
6153         // we now have a bloom image in the framebuffer
6154         // copy it into the bloom image texture for later processing
6155         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);
6156         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6157 }
6158
6159 void R_Bloom_CopyHDRTexture(void)
6160 {
6161         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);
6162         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6163 }
6164
6165 void R_Bloom_MakeTexture(void)
6166 {
6167         int x, range, dir;
6168         float xoffset, yoffset, r, brighten;
6169
6170         r_refdef.stats.bloom++;
6171
6172         R_ResetViewRendering2D();
6173
6174         // we have a bloom image in the framebuffer
6175         CHECKGLERROR
6176         R_SetViewport(&r_bloomstate.viewport);
6177
6178         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6179         {
6180                 x *= 2;
6181                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6182                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6183                 GL_Color(r,r,r,1);
6184                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6185                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6186                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6187                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6188
6189                 // copy the vertically blurred bloom view to a texture
6190                 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);
6191                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6192         }
6193
6194         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6195         brighten = r_bloom_brighten.value;
6196         if (r_bloomstate.hdr)
6197                 brighten *= r_hdr_range.value;
6198         brighten = sqrt(brighten);
6199         if(range >= 1)
6200                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6201         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6202
6203         for (dir = 0;dir < 2;dir++)
6204         {
6205                 // blend on at multiple vertical offsets to achieve a vertical blur
6206                 // TODO: do offset blends using GLSL
6207                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6208                 GL_BlendFunc(GL_ONE, GL_ZERO);
6209                 for (x = -range;x <= range;x++)
6210                 {
6211                         if (!dir){xoffset = 0;yoffset = x;}
6212                         else {xoffset = x;yoffset = 0;}
6213                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6214                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6215                         // compute a texcoord array with the specified x and y offset
6216                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6217                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6218                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6219                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6220                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6221                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6222                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6223                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6224                         // this r value looks like a 'dot' particle, fading sharply to
6225                         // black at the edges
6226                         // (probably not realistic but looks good enough)
6227                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6228                         //r = brighten/(range*2+1);
6229                         r = brighten / (range * 2 + 1);
6230                         if(range >= 1)
6231                                 r *= (1 - x*x/(float)(range*range));
6232                         GL_Color(r, r, r, 1);
6233                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6234                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6235                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6236                         GL_BlendFunc(GL_ONE, GL_ONE);
6237                 }
6238
6239                 // copy the vertically blurred bloom view to a texture
6240                 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);
6241                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6242         }
6243 }
6244
6245 void R_HDR_RenderBloomTexture(void)
6246 {
6247         int oldwidth, oldheight;
6248         float oldcolorscale;
6249         qboolean oldwaterstate;
6250
6251         oldwaterstate = r_waterstate.enabled;
6252         oldcolorscale = r_refdef.view.colorscale;
6253         oldwidth = r_refdef.view.width;
6254         oldheight = r_refdef.view.height;
6255         r_refdef.view.width = r_bloomstate.bloomwidth;
6256         r_refdef.view.height = r_bloomstate.bloomheight;
6257
6258         if(r_hdr.integer < 2)
6259                 r_waterstate.enabled = false;
6260
6261         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6262         // TODO: add exposure compensation features
6263         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6264
6265         r_refdef.view.showdebug = false;
6266         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6267
6268         R_ResetViewRendering3D();
6269
6270         R_ClearScreen(r_refdef.fogenabled);
6271         if (r_timereport_active)
6272                 R_TimeReport("HDRclear");
6273
6274         R_View_Update();
6275         if (r_timereport_active)
6276                 R_TimeReport("visibility");
6277
6278         // only do secondary renders with HDR if r_hdr is 2 or higher
6279         r_waterstate.numwaterplanes = 0;
6280         if (r_waterstate.enabled)
6281                 R_RenderWaterPlanes();
6282
6283         r_refdef.view.showdebug = true;
6284         R_RenderScene();
6285         r_waterstate.numwaterplanes = 0;
6286
6287         R_ResetViewRendering2D();
6288
6289         R_Bloom_CopyHDRTexture();
6290         R_Bloom_MakeTexture();
6291
6292         // restore the view settings
6293         r_waterstate.enabled = oldwaterstate;
6294         r_refdef.view.width = oldwidth;
6295         r_refdef.view.height = oldheight;
6296         r_refdef.view.colorscale = oldcolorscale;
6297
6298         R_ResetViewRendering3D();
6299
6300         R_ClearScreen(r_refdef.fogenabled);
6301         if (r_timereport_active)
6302                 R_TimeReport("viewclear");
6303 }
6304
6305 static void R_BlendView(void)
6306 {
6307         unsigned int permutation;
6308         float uservecs[4][4];
6309
6310         switch (vid.renderpath)
6311         {
6312         case RENDERPATH_GL20:
6313         case RENDERPATH_D3D9:
6314         case RENDERPATH_D3D10:
6315         case RENDERPATH_D3D11:
6316         case RENDERPATH_SOFT:
6317         case RENDERPATH_GLES2:
6318                 permutation =
6319                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6320                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6321                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6322                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6323                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6324
6325                 if (r_bloomstate.texture_screen)
6326                 {
6327                         // make sure the buffer is available
6328                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6329
6330                         R_ResetViewRendering2D();
6331                         R_Mesh_SetMainRenderTargets();
6332
6333                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6334                         {
6335                                 // declare variables
6336                                 float blur_factor, blur_mouseaccel, blur_velocity;
6337                                 static float blur_average; 
6338                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6339
6340                                 // set a goal for the factoring
6341                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6342                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6343                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6344                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6345                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6346                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6347
6348                                 // from the goal, pick an averaged value between goal and last value
6349                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6350                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6351                                 
6352                                 // enforce minimum amount of blur 
6353                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6354                                 
6355                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6356
6357                                 // calculate values into a standard alpha
6358                                 cl.motionbluralpha = 1 - exp(-
6359                                                 (
6360                                                  (r_motionblur.value * blur_factor / 80)
6361                                                  +
6362                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6363                                                 )
6364                                                 /
6365                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6366                                           );
6367                                 
6368                                 // randomization for the blur value to combat persistent ghosting
6369                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6370                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6371                                 
6372                                 // apply the blur
6373                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6374                                 {
6375                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6376                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6377                                         switch(vid.renderpath)
6378                                         {
6379                                         case RENDERPATH_GL11:
6380                                         case RENDERPATH_GL13:
6381                                         case RENDERPATH_GL20:
6382                                         case RENDERPATH_GLES1:
6383                                         case RENDERPATH_GLES2:
6384                                         case RENDERPATH_SOFT:
6385                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6386                                                 break;
6387                                         case RENDERPATH_D3D9:
6388                                         case RENDERPATH_D3D10:
6389                                         case RENDERPATH_D3D11:
6390                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6391                                                 break;
6392                                         }
6393                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6394                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6395                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6396                                 }
6397                                 
6398                                 // updates old view angles for next pass 
6399                                 VectorCopy(cl.viewangles, blur_oldangles);
6400                         }
6401
6402                         // copy view into the screen texture
6403                         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);
6404                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6405                 }
6406                 else if (!r_bloomstate.texture_bloom)
6407                 {
6408                         // we may still have to do view tint...
6409                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6410                         {
6411                                 // apply a color tint to the whole view
6412                                 R_ResetViewRendering2D();
6413                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6414                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6415                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6416                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6417                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6418                         }
6419                         break; // no screen processing, no bloom, skip it
6420                 }
6421
6422                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6423                 {
6424                         // render simple bloom effect
6425                         // copy the screen and shrink it and darken it for the bloom process
6426                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6427                         // make the bloom texture
6428                         R_Bloom_MakeTexture();
6429                 }
6430
6431 #if _MSC_VER >= 1400
6432 #define sscanf sscanf_s
6433 #endif
6434                 memset(uservecs, 0, sizeof(uservecs));
6435                 if (r_glsl_postprocess_uservec1_enable.integer)
6436                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6437                 if (r_glsl_postprocess_uservec2_enable.integer)
6438                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6439                 if (r_glsl_postprocess_uservec3_enable.integer)
6440                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6441                 if (r_glsl_postprocess_uservec4_enable.integer)
6442                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6443
6444                 R_ResetViewRendering2D();
6445                 GL_Color(1, 1, 1, 1);
6446                 GL_BlendFunc(GL_ONE, GL_ZERO);
6447
6448                 switch(vid.renderpath)
6449                 {
6450                 case RENDERPATH_GL20:
6451                 case RENDERPATH_GLES2:
6452                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6453                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6454                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6455                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6456                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6457                         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]);
6458                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6459                         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]);
6460                         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]);
6461                         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]);
6462                         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]);
6463                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6464                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6465                         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);
6466                         break;
6467                 case RENDERPATH_D3D9:
6468 #ifdef SUPPORTD3D
6469                         // 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...
6470                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6471                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6472                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6473                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6474                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6475                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6476                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6477                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6478                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6479                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6480                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6481                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6482                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6483                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6484 #endif
6485                         break;
6486                 case RENDERPATH_D3D10:
6487                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6488                         break;
6489                 case RENDERPATH_D3D11:
6490                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6491                         break;
6492                 case RENDERPATH_SOFT:
6493                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6494                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6495                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6496                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6497                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6498                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6499                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6500                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6501                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6502                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6503                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6504                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6505                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6506                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6507                         break;
6508                 default:
6509                         break;
6510                 }
6511                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6512                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6513                 break;
6514         case RENDERPATH_GL11:
6515         case RENDERPATH_GL13:
6516         case RENDERPATH_GLES1:
6517                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6518                 {
6519                         // apply a color tint to the whole view
6520                         R_ResetViewRendering2D();
6521                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6522                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6523                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6524                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6525                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6526                 }
6527                 break;
6528         }
6529 }
6530
6531 matrix4x4_t r_waterscrollmatrix;
6532
6533 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6534 {
6535         if (r_refdef.fog_density)
6536         {
6537                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6538                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6539                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6540
6541                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6542                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6543                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6544                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6545
6546                 {
6547                         vec3_t fogvec;
6548                         VectorCopy(r_refdef.fogcolor, fogvec);
6549                         //   color.rgb *= ContrastBoost * SceneBrightness;
6550                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6551                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6552                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6553                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6554                 }
6555         }
6556 }
6557
6558 void R_UpdateVariables(void)
6559 {
6560         R_Textures_Frame();
6561
6562         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6563
6564         r_refdef.farclip = r_farclip_base.value;
6565         if (r_refdef.scene.worldmodel)
6566                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6567         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6568
6569         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6570                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6571         r_refdef.polygonfactor = 0;
6572         r_refdef.polygonoffset = 0;
6573         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6574         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6575
6576         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6577         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6578         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6579         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6580         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6581         if (FAKELIGHT_ENABLED)
6582         {
6583                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6584         }
6585         if (r_showsurfaces.integer)
6586         {
6587                 r_refdef.scene.rtworld = false;
6588                 r_refdef.scene.rtworldshadows = false;
6589                 r_refdef.scene.rtdlight = false;
6590                 r_refdef.scene.rtdlightshadows = false;
6591                 r_refdef.lightmapintensity = 0;
6592         }
6593
6594         if (gamemode == GAME_NEHAHRA)
6595         {
6596                 if (gl_fogenable.integer)
6597                 {
6598                         r_refdef.oldgl_fogenable = true;
6599                         r_refdef.fog_density = gl_fogdensity.value;
6600                         r_refdef.fog_red = gl_fogred.value;
6601                         r_refdef.fog_green = gl_foggreen.value;
6602                         r_refdef.fog_blue = gl_fogblue.value;
6603                         r_refdef.fog_alpha = 1;
6604                         r_refdef.fog_start = 0;
6605                         r_refdef.fog_end = gl_skyclip.value;
6606                         r_refdef.fog_height = 1<<30;
6607                         r_refdef.fog_fadedepth = 128;
6608                 }
6609                 else if (r_refdef.oldgl_fogenable)
6610                 {
6611                         r_refdef.oldgl_fogenable = false;
6612                         r_refdef.fog_density = 0;
6613                         r_refdef.fog_red = 0;
6614                         r_refdef.fog_green = 0;
6615                         r_refdef.fog_blue = 0;
6616                         r_refdef.fog_alpha = 0;
6617                         r_refdef.fog_start = 0;
6618                         r_refdef.fog_end = 0;
6619                         r_refdef.fog_height = 1<<30;
6620                         r_refdef.fog_fadedepth = 128;
6621                 }
6622         }
6623
6624         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6625         r_refdef.fog_start = max(0, r_refdef.fog_start);
6626         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6627
6628         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6629
6630         if (r_refdef.fog_density && r_drawfog.integer)
6631         {
6632                 r_refdef.fogenabled = true;
6633                 // this is the point where the fog reaches 0.9986 alpha, which we
6634                 // consider a good enough cutoff point for the texture
6635                 // (0.9986 * 256 == 255.6)
6636                 if (r_fog_exp2.integer)
6637                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6638                 else
6639                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6640                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6641                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6642                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6643                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6644                         R_BuildFogHeightTexture();
6645                 // fog color was already set
6646                 // update the fog texture
6647                 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)
6648                         R_BuildFogTexture();
6649                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6650                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6651         }
6652         else
6653                 r_refdef.fogenabled = false;
6654
6655         switch(vid.renderpath)
6656         {
6657         case RENDERPATH_GL20:
6658         case RENDERPATH_D3D9:
6659         case RENDERPATH_D3D10:
6660         case RENDERPATH_D3D11:
6661         case RENDERPATH_SOFT:
6662         case RENDERPATH_GLES2:
6663                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6664                 {
6665                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6666                         {
6667                                 // build GLSL gamma texture
6668 #define RAMPWIDTH 256
6669                                 unsigned short ramp[RAMPWIDTH * 3];
6670                                 unsigned char rampbgr[RAMPWIDTH][4];
6671                                 int i;
6672
6673                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6674
6675                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6676                                 for(i = 0; i < RAMPWIDTH; ++i)
6677                                 {
6678                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6679                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6680                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6681                                         rampbgr[i][3] = 0;
6682                                 }
6683                                 if (r_texture_gammaramps)
6684                                 {
6685                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6686                                 }
6687                                 else
6688                                 {
6689                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6690                                 }
6691                         }
6692                 }
6693                 else
6694                 {
6695                         // remove GLSL gamma texture
6696                 }
6697                 break;
6698         case RENDERPATH_GL11:
6699         case RENDERPATH_GL13:
6700         case RENDERPATH_GLES1:
6701                 break;
6702         }
6703 }
6704
6705 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6706 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6707 /*
6708 ================
6709 R_SelectScene
6710 ================
6711 */
6712 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6713         if( scenetype != r_currentscenetype ) {
6714                 // store the old scenetype
6715                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6716                 r_currentscenetype = scenetype;
6717                 // move in the new scene
6718                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6719         }
6720 }
6721
6722 /*
6723 ================
6724 R_GetScenePointer
6725 ================
6726 */
6727 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6728 {
6729         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6730         if( scenetype == r_currentscenetype ) {
6731                 return &r_refdef.scene;
6732         } else {
6733                 return &r_scenes_store[ scenetype ];
6734         }
6735 }
6736
6737 /*
6738 ================
6739 R_RenderView
6740 ================
6741 */
6742 int dpsoftrast_test;
6743 extern void R_Shadow_UpdateBounceGridTexture(void);
6744 extern cvar_t r_shadow_bouncegrid;
6745 void R_RenderView(void)
6746 {
6747         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6748
6749         dpsoftrast_test = r_test.integer;
6750
6751         if (r_timereport_active)
6752                 R_TimeReport("start");
6753         r_textureframe++; // used only by R_GetCurrentTexture
6754         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6755
6756         if(R_CompileShader_CheckStaticParms())
6757                 R_GLSL_Restart_f();
6758
6759         if (!r_drawentities.integer)
6760                 r_refdef.scene.numentities = 0;
6761
6762         R_AnimCache_ClearCache();
6763         R_FrameData_NewFrame();
6764
6765         /* adjust for stereo display */
6766         if(R_Stereo_Active())
6767         {
6768                 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);
6769                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6770         }
6771
6772         if (r_refdef.view.isoverlay)
6773         {
6774                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6775                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6776                 R_TimeReport("depthclear");
6777
6778                 r_refdef.view.showdebug = false;
6779
6780                 r_waterstate.enabled = false;
6781                 r_waterstate.numwaterplanes = 0;
6782
6783                 R_RenderScene();
6784
6785                 r_refdef.view.matrix = originalmatrix;
6786
6787                 CHECKGLERROR
6788                 return;
6789         }
6790
6791         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6792         {
6793                 r_refdef.view.matrix = originalmatrix;
6794                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6795         }
6796
6797         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6798
6799         R_RenderView_UpdateViewVectors();
6800
6801         R_Shadow_UpdateWorldLightSelection();
6802
6803         R_Bloom_StartFrame();
6804         R_Water_StartFrame();
6805
6806         CHECKGLERROR
6807         if (r_timereport_active)
6808                 R_TimeReport("viewsetup");
6809
6810         R_ResetViewRendering3D();
6811
6812         if (r_refdef.view.clear || r_refdef.fogenabled)
6813         {
6814                 R_ClearScreen(r_refdef.fogenabled);
6815                 if (r_timereport_active)
6816                         R_TimeReport("viewclear");
6817         }
6818         r_refdef.view.clear = true;
6819
6820         // this produces a bloom texture to be used in R_BlendView() later
6821         if (r_bloomstate.hdr)
6822         {
6823                 R_HDR_RenderBloomTexture();
6824                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6825                 r_textureframe++; // used only by R_GetCurrentTexture
6826         }
6827
6828         r_refdef.view.showdebug = true;
6829
6830         R_View_Update();
6831         if (r_timereport_active)
6832                 R_TimeReport("visibility");
6833
6834         R_Shadow_UpdateBounceGridTexture();
6835         if (r_timereport_active && r_shadow_bouncegrid.integer)
6836                 R_TimeReport("bouncegrid");
6837
6838         r_waterstate.numwaterplanes = 0;
6839         if (r_waterstate.enabled)
6840                 R_RenderWaterPlanes();
6841
6842         R_RenderScene();
6843         r_waterstate.numwaterplanes = 0;
6844
6845         R_BlendView();
6846         if (r_timereport_active)
6847                 R_TimeReport("blendview");
6848
6849         GL_Scissor(0, 0, vid.width, vid.height);
6850         GL_ScissorTest(false);
6851
6852         r_refdef.view.matrix = originalmatrix;
6853
6854         CHECKGLERROR
6855 }
6856
6857 void R_RenderWaterPlanes(void)
6858 {
6859         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6860         {
6861                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6862                 if (r_timereport_active)
6863                         R_TimeReport("waterworld");
6864         }
6865
6866         // don't let sound skip if going slow
6867         if (r_refdef.scene.extraupdate)
6868                 S_ExtraUpdate ();
6869
6870         R_DrawModelsAddWaterPlanes();
6871         if (r_timereport_active)
6872                 R_TimeReport("watermodels");
6873
6874         if (r_waterstate.numwaterplanes)
6875         {
6876                 R_Water_ProcessPlanes();
6877                 if (r_timereport_active)
6878                         R_TimeReport("waterscenes");
6879         }
6880 }
6881
6882 extern void R_DrawLightningBeams (void);
6883 extern void VM_CL_AddPolygonsToMeshQueue (void);
6884 extern void R_DrawPortals (void);
6885 extern cvar_t cl_locs_show;
6886 static void R_DrawLocs(void);
6887 static void R_DrawEntityBBoxes(void);
6888 static void R_DrawModelDecals(void);
6889 extern void R_DrawModelShadows(void);
6890 extern void R_DrawModelShadowMaps(void);
6891 extern cvar_t cl_decals_newsystem;
6892 extern qboolean r_shadow_usingdeferredprepass;
6893 void R_RenderScene(void)
6894 {
6895         qboolean shadowmapping = false;
6896
6897         if (r_timereport_active)
6898                 R_TimeReport("beginscene");
6899
6900         r_refdef.stats.renders++;
6901
6902         R_UpdateFogColor();
6903
6904         // don't let sound skip if going slow
6905         if (r_refdef.scene.extraupdate)
6906                 S_ExtraUpdate ();
6907
6908         R_MeshQueue_BeginScene();
6909
6910         R_SkyStartFrame();
6911
6912         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);
6913
6914         if (r_timereport_active)
6915                 R_TimeReport("skystartframe");
6916
6917         if (cl.csqc_vidvars.drawworld)
6918         {
6919                 // don't let sound skip if going slow
6920                 if (r_refdef.scene.extraupdate)
6921                         S_ExtraUpdate ();
6922
6923                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6924                 {
6925                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6926                         if (r_timereport_active)
6927                                 R_TimeReport("worldsky");
6928                 }
6929
6930                 if (R_DrawBrushModelsSky() && r_timereport_active)
6931                         R_TimeReport("bmodelsky");
6932
6933                 if (skyrendermasked && skyrenderlater)
6934                 {
6935                         // we have to force off the water clipping plane while rendering sky
6936                         R_SetupView(false);
6937                         R_Sky();
6938                         R_SetupView(true);
6939                         if (r_timereport_active)
6940                                 R_TimeReport("sky");
6941                 }
6942         }
6943
6944         R_AnimCache_CacheVisibleEntities();
6945         if (r_timereport_active)
6946                 R_TimeReport("animation");
6947
6948         R_Shadow_PrepareLights();
6949         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6950                 R_Shadow_PrepareModelShadows();
6951         if (r_timereport_active)
6952                 R_TimeReport("preparelights");
6953
6954         if (R_Shadow_ShadowMappingEnabled())
6955                 shadowmapping = true;
6956
6957         if (r_shadow_usingdeferredprepass)
6958                 R_Shadow_DrawPrepass();
6959
6960         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6961         {
6962                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6963                 if (r_timereport_active)
6964                         R_TimeReport("worlddepth");
6965         }
6966         if (r_depthfirst.integer >= 2)
6967         {
6968                 R_DrawModelsDepth();
6969                 if (r_timereport_active)
6970                         R_TimeReport("modeldepth");
6971         }
6972
6973         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6974         {
6975                 R_DrawModelShadowMaps();
6976                 R_ResetViewRendering3D();
6977                 // don't let sound skip if going slow
6978                 if (r_refdef.scene.extraupdate)
6979                         S_ExtraUpdate ();
6980         }
6981
6982         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6983         {
6984                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6985                 if (r_timereport_active)
6986                         R_TimeReport("world");
6987         }
6988
6989         // don't let sound skip if going slow
6990         if (r_refdef.scene.extraupdate)
6991                 S_ExtraUpdate ();
6992
6993         R_DrawModels();
6994         if (r_timereport_active)
6995                 R_TimeReport("models");
6996
6997         // don't let sound skip if going slow
6998         if (r_refdef.scene.extraupdate)
6999                 S_ExtraUpdate ();
7000
7001         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7002         {
7003                 R_DrawModelShadows();
7004                 R_ResetViewRendering3D();
7005                 // don't let sound skip if going slow
7006                 if (r_refdef.scene.extraupdate)
7007                         S_ExtraUpdate ();
7008         }
7009
7010         if (!r_shadow_usingdeferredprepass)
7011         {
7012                 R_Shadow_DrawLights();
7013                 if (r_timereport_active)
7014                         R_TimeReport("rtlights");
7015         }
7016
7017         // don't let sound skip if going slow
7018         if (r_refdef.scene.extraupdate)
7019                 S_ExtraUpdate ();
7020
7021         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7022         {
7023                 R_DrawModelShadows();
7024                 R_ResetViewRendering3D();
7025                 // don't let sound skip if going slow
7026                 if (r_refdef.scene.extraupdate)
7027                         S_ExtraUpdate ();
7028         }
7029
7030         if (cl.csqc_vidvars.drawworld)
7031         {
7032                 if (cl_decals_newsystem.integer)
7033                 {
7034                         R_DrawModelDecals();
7035                         if (r_timereport_active)
7036                                 R_TimeReport("modeldecals");
7037                 }
7038                 else
7039                 {
7040                         R_DrawDecals();
7041                         if (r_timereport_active)
7042                                 R_TimeReport("decals");
7043                 }
7044
7045                 R_DrawParticles();
7046                 if (r_timereport_active)
7047                         R_TimeReport("particles");
7048
7049                 R_DrawExplosions();
7050                 if (r_timereport_active)
7051                         R_TimeReport("explosions");
7052
7053                 R_DrawLightningBeams();
7054                 if (r_timereport_active)
7055                         R_TimeReport("lightning");
7056         }
7057
7058         VM_CL_AddPolygonsToMeshQueue();
7059
7060         if (r_refdef.view.showdebug)
7061         {
7062                 if (cl_locs_show.integer)
7063                 {
7064                         R_DrawLocs();
7065                         if (r_timereport_active)
7066                                 R_TimeReport("showlocs");
7067                 }
7068
7069                 if (r_drawportals.integer)
7070                 {
7071                         R_DrawPortals();
7072                         if (r_timereport_active)
7073                                 R_TimeReport("portals");
7074                 }
7075
7076                 if (r_showbboxes.value > 0)
7077                 {
7078                         R_DrawEntityBBoxes();
7079                         if (r_timereport_active)
7080                                 R_TimeReport("bboxes");
7081                 }
7082         }
7083
7084         if (r_transparent.integer)
7085         {
7086                 R_MeshQueue_RenderTransparent();
7087                 if (r_timereport_active)
7088                         R_TimeReport("drawtrans");
7089         }
7090
7091         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))
7092         {
7093                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7094                 if (r_timereport_active)
7095                         R_TimeReport("worlddebug");
7096                 R_DrawModelsDebug();
7097                 if (r_timereport_active)
7098                         R_TimeReport("modeldebug");
7099         }
7100
7101         if (cl.csqc_vidvars.drawworld)
7102         {
7103                 R_Shadow_DrawCoronas();
7104                 if (r_timereport_active)
7105                         R_TimeReport("coronas");
7106         }
7107
7108 #if 0
7109         {
7110                 GL_DepthTest(false);
7111                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7112                 GL_Color(1, 1, 1, 1);
7113                 qglBegin(GL_POLYGON);
7114                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7115                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7116                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7117                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7118                 qglEnd();
7119                 qglBegin(GL_POLYGON);
7120                 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]);
7121                 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]);
7122                 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]);
7123                 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]);
7124                 qglEnd();
7125                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7126         }
7127 #endif
7128
7129         // don't let sound skip if going slow
7130         if (r_refdef.scene.extraupdate)
7131                 S_ExtraUpdate ();
7132
7133         R_ResetViewRendering2D();
7134 }
7135
7136 static const unsigned short bboxelements[36] =
7137 {
7138         5, 1, 3, 5, 3, 7,
7139         6, 2, 0, 6, 0, 4,
7140         7, 3, 2, 7, 2, 6,
7141         4, 0, 1, 4, 1, 5,
7142         4, 5, 7, 4, 7, 6,
7143         1, 0, 2, 1, 2, 3,
7144 };
7145
7146 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7147 {
7148         int i;
7149         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7150
7151         RSurf_ActiveWorldEntity();
7152
7153         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7154         GL_DepthMask(false);
7155         GL_DepthRange(0, 1);
7156         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7157 //      R_Mesh_ResetTextureState();
7158
7159         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7160         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7161         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7162         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7163         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7164         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7165         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7166         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7167         R_FillColors(color4f, 8, cr, cg, cb, ca);
7168         if (r_refdef.fogenabled)
7169         {
7170                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7171                 {
7172                         f1 = RSurf_FogVertex(v);
7173                         f2 = 1 - f1;
7174                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7175                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7176                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7177                 }
7178         }
7179         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7180         R_Mesh_ResetTextureState();
7181         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7182         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7183 }
7184
7185 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7186 {
7187         int i;
7188         float color[4];
7189         prvm_edict_t *edict;
7190         prvm_prog_t *prog_save = prog;
7191
7192         // this function draws bounding boxes of server entities
7193         if (!sv.active)
7194                 return;
7195
7196         GL_CullFace(GL_NONE);
7197         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7198
7199         prog = 0;
7200         SV_VM_Begin();
7201         for (i = 0;i < numsurfaces;i++)
7202         {
7203                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7204                 switch ((int)PRVM_serveredictfloat(edict, solid))
7205                 {
7206                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7207                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7208                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7209                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7210                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7211                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7212                 }
7213                 color[3] *= r_showbboxes.value;
7214                 color[3] = bound(0, color[3], 1);
7215                 GL_DepthTest(!r_showdisabledepthtest.integer);
7216                 GL_CullFace(r_refdef.view.cullface_front);
7217                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7218         }
7219         SV_VM_End();
7220         prog = prog_save;
7221 }
7222
7223 static void R_DrawEntityBBoxes(void)
7224 {
7225         int i;
7226         prvm_edict_t *edict;
7227         vec3_t center;
7228         prvm_prog_t *prog_save = prog;
7229
7230         // this function draws bounding boxes of server entities
7231         if (!sv.active)
7232                 return;
7233
7234         prog = 0;
7235         SV_VM_Begin();
7236         for (i = 0;i < prog->num_edicts;i++)
7237         {
7238                 edict = PRVM_EDICT_NUM(i);
7239                 if (edict->priv.server->free)
7240                         continue;
7241                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7242                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7243                         continue;
7244                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7245                         continue;
7246                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7247                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7248         }
7249         SV_VM_End();
7250         prog = prog_save;
7251 }
7252
7253 static const int nomodelelement3i[24] =
7254 {
7255         5, 2, 0,
7256         5, 1, 2,
7257         5, 0, 3,
7258         5, 3, 1,
7259         0, 2, 4,
7260         2, 1, 4,
7261         3, 0, 4,
7262         1, 3, 4
7263 };
7264
7265 static const unsigned short nomodelelement3s[24] =
7266 {
7267         5, 2, 0,
7268         5, 1, 2,
7269         5, 0, 3,
7270         5, 3, 1,
7271         0, 2, 4,
7272         2, 1, 4,
7273         3, 0, 4,
7274         1, 3, 4
7275 };
7276
7277 static const float nomodelvertex3f[6*3] =
7278 {
7279         -16,   0,   0,
7280          16,   0,   0,
7281           0, -16,   0,
7282           0,  16,   0,
7283           0,   0, -16,
7284           0,   0,  16
7285 };
7286
7287 static const float nomodelcolor4f[6*4] =
7288 {
7289         0.0f, 0.0f, 0.5f, 1.0f,
7290         0.0f, 0.0f, 0.5f, 1.0f,
7291         0.0f, 0.5f, 0.0f, 1.0f,
7292         0.0f, 0.5f, 0.0f, 1.0f,
7293         0.5f, 0.0f, 0.0f, 1.0f,
7294         0.5f, 0.0f, 0.0f, 1.0f
7295 };
7296
7297 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7298 {
7299         int i;
7300         float f1, f2, *c;
7301         float color4f[6*4];
7302
7303         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);
7304
7305         // this is only called once per entity so numsurfaces is always 1, and
7306         // surfacelist is always {0}, so this code does not handle batches
7307
7308         if (rsurface.ent_flags & RENDER_ADDITIVE)
7309         {
7310                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7311                 GL_DepthMask(false);
7312         }
7313         else if (rsurface.colormod[3] < 1)
7314         {
7315                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7316                 GL_DepthMask(false);
7317         }
7318         else
7319         {
7320                 GL_BlendFunc(GL_ONE, GL_ZERO);
7321                 GL_DepthMask(true);
7322         }
7323         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7324         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7325         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7326         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7327         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7328         for (i = 0, c = color4f;i < 6;i++, c += 4)
7329         {
7330                 c[0] *= rsurface.colormod[0];
7331                 c[1] *= rsurface.colormod[1];
7332                 c[2] *= rsurface.colormod[2];
7333                 c[3] *= rsurface.colormod[3];
7334         }
7335         if (r_refdef.fogenabled)
7336         {
7337                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7338                 {
7339                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7340                         f2 = 1 - f1;
7341                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7342                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7343                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7344                 }
7345         }
7346 //      R_Mesh_ResetTextureState();
7347         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7348         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7349         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7350 }
7351
7352 void R_DrawNoModel(entity_render_t *ent)
7353 {
7354         vec3_t org;
7355         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7356         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7357                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7358         else
7359                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7360 }
7361
7362 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7363 {
7364         vec3_t right1, right2, diff, normal;
7365
7366         VectorSubtract (org2, org1, normal);
7367
7368         // calculate 'right' vector for start
7369         VectorSubtract (r_refdef.view.origin, org1, diff);
7370         CrossProduct (normal, diff, right1);
7371         VectorNormalize (right1);
7372
7373         // calculate 'right' vector for end
7374         VectorSubtract (r_refdef.view.origin, org2, diff);
7375         CrossProduct (normal, diff, right2);
7376         VectorNormalize (right2);
7377
7378         vert[ 0] = org1[0] + width * right1[0];
7379         vert[ 1] = org1[1] + width * right1[1];
7380         vert[ 2] = org1[2] + width * right1[2];
7381         vert[ 3] = org1[0] - width * right1[0];
7382         vert[ 4] = org1[1] - width * right1[1];
7383         vert[ 5] = org1[2] - width * right1[2];
7384         vert[ 6] = org2[0] - width * right2[0];
7385         vert[ 7] = org2[1] - width * right2[1];
7386         vert[ 8] = org2[2] - width * right2[2];
7387         vert[ 9] = org2[0] + width * right2[0];
7388         vert[10] = org2[1] + width * right2[1];
7389         vert[11] = org2[2] + width * right2[2];
7390 }
7391
7392 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)
7393 {
7394         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7395         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7396         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7397         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7398         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7399         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7400         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7401         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7402         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7403         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7404         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7405         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7406 }
7407
7408 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7409 {
7410         int i;
7411         float *vertex3f;
7412         float v[3];
7413         VectorSet(v, x, y, z);
7414         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7415                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7416                         break;
7417         if (i == mesh->numvertices)
7418         {
7419                 if (mesh->numvertices < mesh->maxvertices)
7420                 {
7421                         VectorCopy(v, vertex3f);
7422                         mesh->numvertices++;
7423                 }
7424                 return mesh->numvertices;
7425         }
7426         else
7427                 return i;
7428 }
7429
7430 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7431 {
7432         int i;
7433         int *e, element[3];
7434         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7435         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7436         e = mesh->element3i + mesh->numtriangles * 3;
7437         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7438         {
7439                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7440                 if (mesh->numtriangles < mesh->maxtriangles)
7441                 {
7442                         *e++ = element[0];
7443                         *e++ = element[1];
7444                         *e++ = element[2];
7445                         mesh->numtriangles++;
7446                 }
7447                 element[1] = element[2];
7448         }
7449 }
7450
7451 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7452 {
7453         int i;
7454         int *e, element[3];
7455         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7456         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7457         e = mesh->element3i + mesh->numtriangles * 3;
7458         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7459         {
7460                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7461                 if (mesh->numtriangles < mesh->maxtriangles)
7462                 {
7463                         *e++ = element[0];
7464                         *e++ = element[1];
7465                         *e++ = element[2];
7466                         mesh->numtriangles++;
7467                 }
7468                 element[1] = element[2];
7469         }
7470 }
7471
7472 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7473 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7474 {
7475         int planenum, planenum2;
7476         int w;
7477         int tempnumpoints;
7478         mplane_t *plane, *plane2;
7479         double maxdist;
7480         double temppoints[2][256*3];
7481         // figure out how large a bounding box we need to properly compute this brush
7482         maxdist = 0;
7483         for (w = 0;w < numplanes;w++)
7484                 maxdist = max(maxdist, fabs(planes[w].dist));
7485         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7486         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7487         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7488         {
7489                 w = 0;
7490                 tempnumpoints = 4;
7491                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7492                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7493                 {
7494                         if (planenum2 == planenum)
7495                                 continue;
7496                         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);
7497                         w = !w;
7498                 }
7499                 if (tempnumpoints < 3)
7500                         continue;
7501                 // generate elements forming a triangle fan for this polygon
7502                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7503         }
7504 }
7505
7506 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)
7507 {
7508         texturelayer_t *layer;
7509         layer = t->currentlayers + t->currentnumlayers++;
7510         layer->type = type;
7511         layer->depthmask = depthmask;
7512         layer->blendfunc1 = blendfunc1;
7513         layer->blendfunc2 = blendfunc2;
7514         layer->texture = texture;
7515         layer->texmatrix = *matrix;
7516         layer->color[0] = r;
7517         layer->color[1] = g;
7518         layer->color[2] = b;
7519         layer->color[3] = a;
7520 }
7521
7522 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7523 {
7524         if(parms[0] == 0 && parms[1] == 0)
7525                 return false;
7526         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7527                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7528                         return false;
7529         return true;
7530 }
7531
7532 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7533 {
7534         double index, f;
7535         index = parms[2] + rsurface.shadertime * parms[3];
7536         index -= floor(index);
7537         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7538         {
7539         default:
7540         case Q3WAVEFUNC_NONE:
7541         case Q3WAVEFUNC_NOISE:
7542         case Q3WAVEFUNC_COUNT:
7543                 f = 0;
7544                 break;
7545         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7546         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7547         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7548         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7549         case Q3WAVEFUNC_TRIANGLE:
7550                 index *= 4;
7551                 f = index - floor(index);
7552                 if (index < 1)
7553                 {
7554                         // f = f;
7555                 }
7556                 else if (index < 2)
7557                         f = 1 - f;
7558                 else if (index < 3)
7559                         f = -f;
7560                 else
7561                         f = -(1 - f);
7562                 break;
7563         }
7564         f = parms[0] + parms[1] * f;
7565         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7566                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7567         return (float) f;
7568 }
7569
7570 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7571 {
7572         int w, h, idx;
7573         double f;
7574         double offsetd[2];
7575         float tcmat[12];
7576         matrix4x4_t matrix, temp;
7577         switch(tcmod->tcmod)
7578         {
7579                 case Q3TCMOD_COUNT:
7580                 case Q3TCMOD_NONE:
7581                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7582                                 matrix = r_waterscrollmatrix;
7583                         else
7584                                 matrix = identitymatrix;
7585                         break;
7586                 case Q3TCMOD_ENTITYTRANSLATE:
7587                         // this is used in Q3 to allow the gamecode to control texcoord
7588                         // scrolling on the entity, which is not supported in darkplaces yet.
7589                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7590                         break;
7591                 case Q3TCMOD_ROTATE:
7592                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7593                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7594                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7595                         break;
7596                 case Q3TCMOD_SCALE:
7597                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7598                         break;
7599                 case Q3TCMOD_SCROLL:
7600                         // extra care is needed because of precision breakdown with large values of time
7601                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7602                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7603                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7604                         break;
7605                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7606                         w = (int) tcmod->parms[0];
7607                         h = (int) tcmod->parms[1];
7608                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7609                         f = f - floor(f);
7610                         idx = (int) floor(f * w * h);
7611                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7612                         break;
7613                 case Q3TCMOD_STRETCH:
7614                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7615                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7616                         break;
7617                 case Q3TCMOD_TRANSFORM:
7618                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7619                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7620                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7621                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7622                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7623                         break;
7624                 case Q3TCMOD_TURBULENT:
7625                         // this is handled in the RSurf_PrepareVertices function
7626                         matrix = identitymatrix;
7627                         break;
7628         }
7629         temp = *texmatrix;
7630         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7631 }
7632
7633 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7634 {
7635         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7636         char name[MAX_QPATH];
7637         skinframe_t *skinframe;
7638         unsigned char pixels[296*194];
7639         strlcpy(cache->name, skinname, sizeof(cache->name));
7640         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7641         if (developer_loading.integer)
7642                 Con_Printf("loading %s\n", name);
7643         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7644         if (!skinframe || !skinframe->base)
7645         {
7646                 unsigned char *f;
7647                 fs_offset_t filesize;
7648                 skinframe = NULL;
7649                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7650                 if (f)
7651                 {
7652                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7653                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7654                         Mem_Free(f);
7655                 }
7656         }
7657         cache->skinframe = skinframe;
7658 }
7659
7660 texture_t *R_GetCurrentTexture(texture_t *t)
7661 {
7662         int i;
7663         const entity_render_t *ent = rsurface.entity;
7664         dp_model_t *model = ent->model;
7665         q3shaderinfo_layer_tcmod_t *tcmod;
7666
7667         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7668                 return t->currentframe;
7669         t->update_lastrenderframe = r_textureframe;
7670         t->update_lastrenderentity = (void *)ent;
7671
7672         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7673                 t->camera_entity = ent->entitynumber;
7674         else
7675                 t->camera_entity = 0;
7676
7677         // switch to an alternate material if this is a q1bsp animated material
7678         {
7679                 texture_t *texture = t;
7680                 int s = rsurface.ent_skinnum;
7681                 if ((unsigned int)s >= (unsigned int)model->numskins)
7682                         s = 0;
7683                 if (model->skinscenes)
7684                 {
7685                         if (model->skinscenes[s].framecount > 1)
7686                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7687                         else
7688                                 s = model->skinscenes[s].firstframe;
7689                 }
7690                 if (s > 0)
7691                         t = t + s * model->num_surfaces;
7692                 if (t->animated)
7693                 {
7694                         // use an alternate animation if the entity's frame is not 0,
7695                         // and only if the texture has an alternate animation
7696                         if (rsurface.ent_alttextures && t->anim_total[1])
7697                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7698                         else
7699                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7700                 }
7701                 texture->currentframe = t;
7702         }
7703
7704         // update currentskinframe to be a qw skin or animation frame
7705         if (rsurface.ent_qwskin >= 0)
7706         {
7707                 i = rsurface.ent_qwskin;
7708                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7709                 {
7710                         r_qwskincache_size = cl.maxclients;
7711                         if (r_qwskincache)
7712                                 Mem_Free(r_qwskincache);
7713                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7714                 }
7715                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7716                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7717                 t->currentskinframe = r_qwskincache[i].skinframe;
7718                 if (t->currentskinframe == NULL)
7719                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7720         }
7721         else if (t->numskinframes >= 2)
7722                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7723         if (t->backgroundnumskinframes >= 2)
7724                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7725
7726         t->currentmaterialflags = t->basematerialflags;
7727         t->currentalpha = rsurface.colormod[3];
7728         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7729                 t->currentalpha *= r_wateralpha.value;
7730         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7731                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7732         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7733                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7734         if (!(rsurface.ent_flags & RENDER_LIGHT))
7735                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7736         else if (FAKELIGHT_ENABLED)
7737         {
7738                 // no modellight if using fakelight for the map
7739         }
7740         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7741         {
7742                 // pick a model lighting mode
7743                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7744                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7745                 else
7746                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7747         }
7748         if (rsurface.ent_flags & RENDER_ADDITIVE)
7749                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7750         else if (t->currentalpha < 1)
7751                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7752         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7753                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7754         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7755                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7756         if (t->backgroundnumskinframes)
7757                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7758         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7759         {
7760                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7761                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7762         }
7763         else
7764                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7765         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7766         {
7767                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7768                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7769         }
7770         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7771                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7772
7773         // there is no tcmod
7774         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7775         {
7776                 t->currenttexmatrix = r_waterscrollmatrix;
7777                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7778         }
7779         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7780         {
7781                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7782                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7783         }
7784
7785         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7786                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7787         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7788                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7789
7790         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7791         if (t->currentskinframe->qpixels)
7792                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7793         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7794         if (!t->basetexture)
7795                 t->basetexture = r_texture_notexture;
7796         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7797         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7798         t->nmaptexture = t->currentskinframe->nmap;
7799         if (!t->nmaptexture)
7800                 t->nmaptexture = r_texture_blanknormalmap;
7801         t->glosstexture = r_texture_black;
7802         t->glowtexture = t->currentskinframe->glow;
7803         t->fogtexture = t->currentskinframe->fog;
7804         t->reflectmasktexture = t->currentskinframe->reflect;
7805         if (t->backgroundnumskinframes)
7806         {
7807                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7808                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7809                 t->backgroundglosstexture = r_texture_black;
7810                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7811                 if (!t->backgroundnmaptexture)
7812                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7813         }
7814         else
7815         {
7816                 t->backgroundbasetexture = r_texture_white;
7817                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7818                 t->backgroundglosstexture = r_texture_black;
7819                 t->backgroundglowtexture = NULL;
7820         }
7821         t->specularpower = r_shadow_glossexponent.value;
7822         // TODO: store reference values for these in the texture?
7823         t->specularscale = 0;
7824         if (r_shadow_gloss.integer > 0)
7825         {
7826                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7827                 {
7828                         if (r_shadow_glossintensity.value > 0)
7829                         {
7830                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7831                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7832                                 t->specularscale = r_shadow_glossintensity.value;
7833                         }
7834                 }
7835                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7836                 {
7837                         t->glosstexture = r_texture_white;
7838                         t->backgroundglosstexture = r_texture_white;
7839                         t->specularscale = r_shadow_gloss2intensity.value;
7840                         t->specularpower = r_shadow_gloss2exponent.value;
7841                 }
7842         }
7843         t->specularscale *= t->specularscalemod;
7844         t->specularpower *= t->specularpowermod;
7845
7846         // lightmaps mode looks bad with dlights using actual texturing, so turn
7847         // off the colormap and glossmap, but leave the normalmap on as it still
7848         // accurately represents the shading involved
7849         if (gl_lightmaps.integer)
7850         {
7851                 t->basetexture = r_texture_grey128;
7852                 t->pantstexture = r_texture_black;
7853                 t->shirttexture = r_texture_black;
7854                 t->nmaptexture = r_texture_blanknormalmap;
7855                 t->glosstexture = r_texture_black;
7856                 t->glowtexture = NULL;
7857                 t->fogtexture = NULL;
7858                 t->reflectmasktexture = NULL;
7859                 t->backgroundbasetexture = NULL;
7860                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7861                 t->backgroundglosstexture = r_texture_black;
7862                 t->backgroundglowtexture = NULL;
7863                 t->specularscale = 0;
7864                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7865         }
7866
7867         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7868         VectorClear(t->dlightcolor);
7869         t->currentnumlayers = 0;
7870         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7871         {
7872                 int blendfunc1, blendfunc2;
7873                 qboolean depthmask;
7874                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7875                 {
7876                         blendfunc1 = GL_SRC_ALPHA;
7877                         blendfunc2 = GL_ONE;
7878                 }
7879                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7880                 {
7881                         blendfunc1 = GL_SRC_ALPHA;
7882                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7883                 }
7884                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7885                 {
7886                         blendfunc1 = t->customblendfunc[0];
7887                         blendfunc2 = t->customblendfunc[1];
7888                 }
7889                 else
7890                 {
7891                         blendfunc1 = GL_ONE;
7892                         blendfunc2 = GL_ZERO;
7893                 }
7894                 // don't colormod evilblend textures
7895                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7896                         VectorSet(t->lightmapcolor, 1, 1, 1);
7897                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7898                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7899                 {
7900                         // fullbright is not affected by r_refdef.lightmapintensity
7901                         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]);
7902                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7903                                 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]);
7904                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7905                                 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]);
7906                 }
7907                 else
7908                 {
7909                         vec3_t ambientcolor;
7910                         float colorscale;
7911                         // set the color tint used for lights affecting this surface
7912                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7913                         colorscale = 2;
7914                         // q3bsp has no lightmap updates, so the lightstylevalue that
7915                         // would normally be baked into the lightmap must be
7916                         // applied to the color
7917                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7918                         if (model->type == mod_brushq3)
7919                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7920                         colorscale *= r_refdef.lightmapintensity;
7921                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7922                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7923                         // basic lit geometry
7924                         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]);
7925                         // add pants/shirt if needed
7926                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7927                                 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]);
7928                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7929                                 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]);
7930                         // now add ambient passes if needed
7931                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7932                         {
7933                                 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]);
7934                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7935                                         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]);
7936                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7937                                         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]);
7938                         }
7939                 }
7940                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7941                         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]);
7942                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7943                 {
7944                         // if this is opaque use alpha blend which will darken the earlier
7945                         // passes cheaply.
7946                         //
7947                         // if this is an alpha blended material, all the earlier passes
7948                         // were darkened by fog already, so we only need to add the fog
7949                         // color ontop through the fog mask texture
7950                         //
7951                         // if this is an additive blended material, all the earlier passes
7952                         // were darkened by fog already, and we should not add fog color
7953                         // (because the background was not darkened, there is no fog color
7954                         // that was lost behind it).
7955                         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]);
7956                 }
7957         }
7958
7959         return t->currentframe;
7960 }
7961
7962 rsurfacestate_t rsurface;
7963
7964 void RSurf_ActiveWorldEntity(void)
7965 {
7966         dp_model_t *model = r_refdef.scene.worldmodel;
7967         //if (rsurface.entity == r_refdef.scene.worldentity)
7968         //      return;
7969         rsurface.entity = r_refdef.scene.worldentity;
7970         rsurface.skeleton = NULL;
7971         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7972         rsurface.ent_skinnum = 0;
7973         rsurface.ent_qwskin = -1;
7974         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7975         rsurface.shadertime = r_refdef.scene.time;
7976         rsurface.matrix = identitymatrix;
7977         rsurface.inversematrix = identitymatrix;
7978         rsurface.matrixscale = 1;
7979         rsurface.inversematrixscale = 1;
7980         R_EntityMatrix(&identitymatrix);
7981         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7982         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7983         rsurface.fograngerecip = r_refdef.fograngerecip;
7984         rsurface.fogheightfade = r_refdef.fogheightfade;
7985         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7986         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7987         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7988         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7989         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7990         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7991         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7992         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7993         rsurface.colormod[3] = 1;
7994         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);
7995         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7996         rsurface.frameblend[0].lerp = 1;
7997         rsurface.ent_alttextures = false;
7998         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7999         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8000         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8001         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8002         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8003         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8004         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8005         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8006         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8007         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8008         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8009         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8010         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8011         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8012         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8013         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8014         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8015         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8016         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8017         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8018         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8019         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8020         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8021         rsurface.modelelement3i = model->surfmesh.data_element3i;
8022         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8023         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8024         rsurface.modelelement3s = model->surfmesh.data_element3s;
8025         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8026         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8027         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8028         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8029         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8030         rsurface.modelsurfaces = model->data_surfaces;
8031         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8032         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8033         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8034         rsurface.modelgeneratedvertex = false;
8035         rsurface.batchgeneratedvertex = false;
8036         rsurface.batchfirstvertex = 0;
8037         rsurface.batchnumvertices = 0;
8038         rsurface.batchfirsttriangle = 0;
8039         rsurface.batchnumtriangles = 0;
8040         rsurface.batchvertex3f  = NULL;
8041         rsurface.batchvertex3f_vertexbuffer = NULL;
8042         rsurface.batchvertex3f_bufferoffset = 0;
8043         rsurface.batchsvector3f = NULL;
8044         rsurface.batchsvector3f_vertexbuffer = NULL;
8045         rsurface.batchsvector3f_bufferoffset = 0;
8046         rsurface.batchtvector3f = NULL;
8047         rsurface.batchtvector3f_vertexbuffer = NULL;
8048         rsurface.batchtvector3f_bufferoffset = 0;
8049         rsurface.batchnormal3f  = NULL;
8050         rsurface.batchnormal3f_vertexbuffer = NULL;
8051         rsurface.batchnormal3f_bufferoffset = 0;
8052         rsurface.batchlightmapcolor4f = NULL;
8053         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8054         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8055         rsurface.batchtexcoordtexture2f = NULL;
8056         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8057         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8058         rsurface.batchtexcoordlightmap2f = NULL;
8059         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8060         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8061         rsurface.batchvertexmesh = NULL;
8062         rsurface.batchvertexmeshbuffer = NULL;
8063         rsurface.batchvertex3fbuffer = NULL;
8064         rsurface.batchelement3i = NULL;
8065         rsurface.batchelement3i_indexbuffer = NULL;
8066         rsurface.batchelement3i_bufferoffset = 0;
8067         rsurface.batchelement3s = NULL;
8068         rsurface.batchelement3s_indexbuffer = NULL;
8069         rsurface.batchelement3s_bufferoffset = 0;
8070         rsurface.passcolor4f = NULL;
8071         rsurface.passcolor4f_vertexbuffer = NULL;
8072         rsurface.passcolor4f_bufferoffset = 0;
8073 }
8074
8075 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8076 {
8077         dp_model_t *model = ent->model;
8078         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8079         //      return;
8080         rsurface.entity = (entity_render_t *)ent;
8081         rsurface.skeleton = ent->skeleton;
8082         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8083         rsurface.ent_skinnum = ent->skinnum;
8084         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;
8085         rsurface.ent_flags = ent->flags;
8086         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8087         rsurface.matrix = ent->matrix;
8088         rsurface.inversematrix = ent->inversematrix;
8089         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8090         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8091         R_EntityMatrix(&rsurface.matrix);
8092         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8093         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8094         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8095         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8096         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8097         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8098         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8099         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8100         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8101         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8102         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8103         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8104         rsurface.colormod[3] = ent->alpha;
8105         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8106         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8107         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8108         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8109         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8110         if (ent->model->brush.submodel && !prepass)
8111         {
8112                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8113                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8114         }
8115         if (model->surfmesh.isanimated && model->AnimateVertices)
8116         {
8117                 if (ent->animcache_vertex3f)
8118                 {
8119                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8120                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8121                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8122                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8123                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8124                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8125                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8126                 }
8127                 else if (wanttangents)
8128                 {
8129                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8130                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8131                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8132                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8133                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8134                         rsurface.modelvertexmesh = NULL;
8135                         rsurface.modelvertexmeshbuffer = NULL;
8136                         rsurface.modelvertex3fbuffer = NULL;
8137                 }
8138                 else if (wantnormals)
8139                 {
8140                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8141                         rsurface.modelsvector3f = NULL;
8142                         rsurface.modeltvector3f = NULL;
8143                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8144                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8145                         rsurface.modelvertexmesh = NULL;
8146                         rsurface.modelvertexmeshbuffer = NULL;
8147                         rsurface.modelvertex3fbuffer = NULL;
8148                 }
8149                 else
8150                 {
8151                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8152                         rsurface.modelsvector3f = NULL;
8153                         rsurface.modeltvector3f = NULL;
8154                         rsurface.modelnormal3f = NULL;
8155                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8156                         rsurface.modelvertexmesh = NULL;
8157                         rsurface.modelvertexmeshbuffer = NULL;
8158                         rsurface.modelvertex3fbuffer = NULL;
8159                 }
8160                 rsurface.modelvertex3f_vertexbuffer = 0;
8161                 rsurface.modelvertex3f_bufferoffset = 0;
8162                 rsurface.modelsvector3f_vertexbuffer = 0;
8163                 rsurface.modelsvector3f_bufferoffset = 0;
8164                 rsurface.modeltvector3f_vertexbuffer = 0;
8165                 rsurface.modeltvector3f_bufferoffset = 0;
8166                 rsurface.modelnormal3f_vertexbuffer = 0;
8167                 rsurface.modelnormal3f_bufferoffset = 0;
8168                 rsurface.modelgeneratedvertex = true;
8169         }
8170         else
8171         {
8172                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8173                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8174                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8175                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8176                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8177                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8178                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8179                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8180                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8181                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8182                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8183                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8184                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8185                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8186                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8187                 rsurface.modelgeneratedvertex = false;
8188         }
8189         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8190         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8191         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8192         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8193         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8194         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8195         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8196         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8197         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8198         rsurface.modelelement3i = model->surfmesh.data_element3i;
8199         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8200         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8201         rsurface.modelelement3s = model->surfmesh.data_element3s;
8202         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8203         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8204         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8205         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8206         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8207         rsurface.modelsurfaces = model->data_surfaces;
8208         rsurface.batchgeneratedvertex = false;
8209         rsurface.batchfirstvertex = 0;
8210         rsurface.batchnumvertices = 0;
8211         rsurface.batchfirsttriangle = 0;
8212         rsurface.batchnumtriangles = 0;
8213         rsurface.batchvertex3f  = NULL;
8214         rsurface.batchvertex3f_vertexbuffer = NULL;
8215         rsurface.batchvertex3f_bufferoffset = 0;
8216         rsurface.batchsvector3f = NULL;
8217         rsurface.batchsvector3f_vertexbuffer = NULL;
8218         rsurface.batchsvector3f_bufferoffset = 0;
8219         rsurface.batchtvector3f = NULL;
8220         rsurface.batchtvector3f_vertexbuffer = NULL;
8221         rsurface.batchtvector3f_bufferoffset = 0;
8222         rsurface.batchnormal3f  = NULL;
8223         rsurface.batchnormal3f_vertexbuffer = NULL;
8224         rsurface.batchnormal3f_bufferoffset = 0;
8225         rsurface.batchlightmapcolor4f = NULL;
8226         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8227         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8228         rsurface.batchtexcoordtexture2f = NULL;
8229         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8230         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8231         rsurface.batchtexcoordlightmap2f = NULL;
8232         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8233         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8234         rsurface.batchvertexmesh = NULL;
8235         rsurface.batchvertexmeshbuffer = NULL;
8236         rsurface.batchvertex3fbuffer = NULL;
8237         rsurface.batchelement3i = NULL;
8238         rsurface.batchelement3i_indexbuffer = NULL;
8239         rsurface.batchelement3i_bufferoffset = 0;
8240         rsurface.batchelement3s = NULL;
8241         rsurface.batchelement3s_indexbuffer = NULL;
8242         rsurface.batchelement3s_bufferoffset = 0;
8243         rsurface.passcolor4f = NULL;
8244         rsurface.passcolor4f_vertexbuffer = NULL;
8245         rsurface.passcolor4f_bufferoffset = 0;
8246 }
8247
8248 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)
8249 {
8250         rsurface.entity = r_refdef.scene.worldentity;
8251         rsurface.skeleton = NULL;
8252         rsurface.ent_skinnum = 0;
8253         rsurface.ent_qwskin = -1;
8254         rsurface.ent_flags = entflags;
8255         rsurface.shadertime = r_refdef.scene.time - shadertime;
8256         rsurface.modelnumvertices = numvertices;
8257         rsurface.modelnumtriangles = numtriangles;
8258         rsurface.matrix = *matrix;
8259         rsurface.inversematrix = *inversematrix;
8260         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8261         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8262         R_EntityMatrix(&rsurface.matrix);
8263         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8264         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8265         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8266         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8267         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8268         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8269         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8270         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8271         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8272         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8273         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8274         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8275         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);
8276         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8277         rsurface.frameblend[0].lerp = 1;
8278         rsurface.ent_alttextures = false;
8279         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8280         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8281         if (wanttangents)
8282         {
8283                 rsurface.modelvertex3f = (float *)vertex3f;
8284                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8285                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8286                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8287         }
8288         else if (wantnormals)
8289         {
8290                 rsurface.modelvertex3f = (float *)vertex3f;
8291                 rsurface.modelsvector3f = NULL;
8292                 rsurface.modeltvector3f = NULL;
8293                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8294         }
8295         else
8296         {
8297                 rsurface.modelvertex3f = (float *)vertex3f;
8298                 rsurface.modelsvector3f = NULL;
8299                 rsurface.modeltvector3f = NULL;
8300                 rsurface.modelnormal3f = NULL;
8301         }
8302         rsurface.modelvertexmesh = NULL;
8303         rsurface.modelvertexmeshbuffer = NULL;
8304         rsurface.modelvertex3fbuffer = NULL;
8305         rsurface.modelvertex3f_vertexbuffer = 0;
8306         rsurface.modelvertex3f_bufferoffset = 0;
8307         rsurface.modelsvector3f_vertexbuffer = 0;
8308         rsurface.modelsvector3f_bufferoffset = 0;
8309         rsurface.modeltvector3f_vertexbuffer = 0;
8310         rsurface.modeltvector3f_bufferoffset = 0;
8311         rsurface.modelnormal3f_vertexbuffer = 0;
8312         rsurface.modelnormal3f_bufferoffset = 0;
8313         rsurface.modelgeneratedvertex = true;
8314         rsurface.modellightmapcolor4f  = (float *)color4f;
8315         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8316         rsurface.modellightmapcolor4f_bufferoffset = 0;
8317         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8318         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8319         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8320         rsurface.modeltexcoordlightmap2f  = NULL;
8321         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8322         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8323         rsurface.modelelement3i = (int *)element3i;
8324         rsurface.modelelement3i_indexbuffer = NULL;
8325         rsurface.modelelement3i_bufferoffset = 0;
8326         rsurface.modelelement3s = (unsigned short *)element3s;
8327         rsurface.modelelement3s_indexbuffer = NULL;
8328         rsurface.modelelement3s_bufferoffset = 0;
8329         rsurface.modellightmapoffsets = NULL;
8330         rsurface.modelsurfaces = NULL;
8331         rsurface.batchgeneratedvertex = false;
8332         rsurface.batchfirstvertex = 0;
8333         rsurface.batchnumvertices = 0;
8334         rsurface.batchfirsttriangle = 0;
8335         rsurface.batchnumtriangles = 0;
8336         rsurface.batchvertex3f  = NULL;
8337         rsurface.batchvertex3f_vertexbuffer = NULL;
8338         rsurface.batchvertex3f_bufferoffset = 0;
8339         rsurface.batchsvector3f = NULL;
8340         rsurface.batchsvector3f_vertexbuffer = NULL;
8341         rsurface.batchsvector3f_bufferoffset = 0;
8342         rsurface.batchtvector3f = NULL;
8343         rsurface.batchtvector3f_vertexbuffer = NULL;
8344         rsurface.batchtvector3f_bufferoffset = 0;
8345         rsurface.batchnormal3f  = NULL;
8346         rsurface.batchnormal3f_vertexbuffer = NULL;
8347         rsurface.batchnormal3f_bufferoffset = 0;
8348         rsurface.batchlightmapcolor4f = NULL;
8349         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8350         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8351         rsurface.batchtexcoordtexture2f = NULL;
8352         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8353         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8354         rsurface.batchtexcoordlightmap2f = NULL;
8355         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8356         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8357         rsurface.batchvertexmesh = NULL;
8358         rsurface.batchvertexmeshbuffer = NULL;
8359         rsurface.batchvertex3fbuffer = NULL;
8360         rsurface.batchelement3i = NULL;
8361         rsurface.batchelement3i_indexbuffer = NULL;
8362         rsurface.batchelement3i_bufferoffset = 0;
8363         rsurface.batchelement3s = NULL;
8364         rsurface.batchelement3s_indexbuffer = NULL;
8365         rsurface.batchelement3s_bufferoffset = 0;
8366         rsurface.passcolor4f = NULL;
8367         rsurface.passcolor4f_vertexbuffer = NULL;
8368         rsurface.passcolor4f_bufferoffset = 0;
8369
8370         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8371         {
8372                 if ((wantnormals || wanttangents) && !normal3f)
8373                 {
8374                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8375                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8376                 }
8377                 if (wanttangents && !svector3f)
8378                 {
8379                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8380                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8381                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8382                 }
8383         }
8384 }
8385
8386 float RSurf_FogPoint(const float *v)
8387 {
8388         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8389         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8390         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8391         float FogHeightFade = r_refdef.fogheightfade;
8392         float fogfrac;
8393         unsigned int fogmasktableindex;
8394         if (r_refdef.fogplaneviewabove)
8395                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8396         else
8397                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8398         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8399         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8400 }
8401
8402 float RSurf_FogVertex(const float *v)
8403 {
8404         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8405         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8406         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8407         float FogHeightFade = rsurface.fogheightfade;
8408         float fogfrac;
8409         unsigned int fogmasktableindex;
8410         if (r_refdef.fogplaneviewabove)
8411                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8412         else
8413                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8414         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8415         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8416 }
8417
8418 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8419 {
8420         int i;
8421         for (i = 0;i < numelements;i++)
8422                 outelement3i[i] = inelement3i[i] + adjust;
8423 }
8424
8425 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8426 extern cvar_t gl_vbo;
8427 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8428 {
8429         int deformindex;
8430         int firsttriangle;
8431         int numtriangles;
8432         int firstvertex;
8433         int endvertex;
8434         int numvertices;
8435         int surfacefirsttriangle;
8436         int surfacenumtriangles;
8437         int surfacefirstvertex;
8438         int surfaceendvertex;
8439         int surfacenumvertices;
8440         int batchnumvertices;
8441         int batchnumtriangles;
8442         int needsupdate;
8443         int i, j;
8444         qboolean gaps;
8445         qboolean dynamicvertex;
8446         float amplitude;
8447         float animpos;
8448         float scale;
8449         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8450         float waveparms[4];
8451         q3shaderinfo_deform_t *deform;
8452         const msurface_t *surface, *firstsurface;
8453         r_vertexmesh_t *vertexmesh;
8454         if (!texturenumsurfaces)
8455                 return;
8456         // find vertex range of this surface batch
8457         gaps = false;
8458         firstsurface = texturesurfacelist[0];
8459         firsttriangle = firstsurface->num_firsttriangle;
8460         batchnumvertices = 0;
8461         batchnumtriangles = 0;
8462         firstvertex = endvertex = firstsurface->num_firstvertex;
8463         for (i = 0;i < texturenumsurfaces;i++)
8464         {
8465                 surface = texturesurfacelist[i];
8466                 if (surface != firstsurface + i)
8467                         gaps = true;
8468                 surfacefirstvertex = surface->num_firstvertex;
8469                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8470                 surfacenumvertices = surface->num_vertices;
8471                 surfacenumtriangles = surface->num_triangles;
8472                 if (firstvertex > surfacefirstvertex)
8473                         firstvertex = surfacefirstvertex;
8474                 if (endvertex < surfaceendvertex)
8475                         endvertex = surfaceendvertex;
8476                 batchnumvertices += surfacenumvertices;
8477                 batchnumtriangles += surfacenumtriangles;
8478         }
8479
8480         // we now know the vertex range used, and if there are any gaps in it
8481         rsurface.batchfirstvertex = firstvertex;
8482         rsurface.batchnumvertices = endvertex - firstvertex;
8483         rsurface.batchfirsttriangle = firsttriangle;
8484         rsurface.batchnumtriangles = batchnumtriangles;
8485
8486         // this variable holds flags for which properties have been updated that
8487         // may require regenerating vertexmesh array...
8488         needsupdate = 0;
8489
8490         // check if any dynamic vertex processing must occur
8491         dynamicvertex = false;
8492
8493         // if there is a chance of animated vertex colors, it's a dynamic batch
8494         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8495         {
8496                 dynamicvertex = true;
8497                 batchneed |= BATCHNEED_NOGAPS;
8498                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8499         }
8500
8501         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8502         {
8503                 switch (deform->deform)
8504                 {
8505                 default:
8506                 case Q3DEFORM_PROJECTIONSHADOW:
8507                 case Q3DEFORM_TEXT0:
8508                 case Q3DEFORM_TEXT1:
8509                 case Q3DEFORM_TEXT2:
8510                 case Q3DEFORM_TEXT3:
8511                 case Q3DEFORM_TEXT4:
8512                 case Q3DEFORM_TEXT5:
8513                 case Q3DEFORM_TEXT6:
8514                 case Q3DEFORM_TEXT7:
8515                 case Q3DEFORM_NONE:
8516                         break;
8517                 case Q3DEFORM_AUTOSPRITE:
8518                         dynamicvertex = true;
8519                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8520                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8521                         break;
8522                 case Q3DEFORM_AUTOSPRITE2:
8523                         dynamicvertex = true;
8524                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8525                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8526                         break;
8527                 case Q3DEFORM_NORMAL:
8528                         dynamicvertex = true;
8529                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8530                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8531                         break;
8532                 case Q3DEFORM_WAVE:
8533                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8534                                 break; // if wavefunc is a nop, ignore this transform
8535                         dynamicvertex = true;
8536                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8537                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8538                         break;
8539                 case Q3DEFORM_BULGE:
8540                         dynamicvertex = true;
8541                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8542                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8543                         break;
8544                 case Q3DEFORM_MOVE:
8545                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8546                                 break; // if wavefunc is a nop, ignore this transform
8547                         dynamicvertex = true;
8548                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8549                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8550                         break;
8551                 }
8552         }
8553         switch(rsurface.texture->tcgen.tcgen)
8554         {
8555         default:
8556         case Q3TCGEN_TEXTURE:
8557                 break;
8558         case Q3TCGEN_LIGHTMAP:
8559                 dynamicvertex = true;
8560                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8561                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8562                 break;
8563         case Q3TCGEN_VECTOR:
8564                 dynamicvertex = true;
8565                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8566                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8567                 break;
8568         case Q3TCGEN_ENVIRONMENT:
8569                 dynamicvertex = true;
8570                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8571                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8572                 break;
8573         }
8574         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8575         {
8576                 dynamicvertex = true;
8577                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8578                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8579         }
8580
8581         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8582         {
8583                 dynamicvertex = true;
8584                 batchneed |= BATCHNEED_NOGAPS;
8585                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8586         }
8587
8588         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8589         {
8590                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8591                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8592                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8593                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8594                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8595                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8596                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8597         }
8598
8599         // when the model data has no vertex buffer (dynamic mesh), we need to
8600         // eliminate gaps
8601         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8602                 batchneed |= BATCHNEED_NOGAPS;
8603
8604         // if needsupdate, we have to do a dynamic vertex batch for sure
8605         if (needsupdate & batchneed)
8606                 dynamicvertex = true;
8607
8608         // see if we need to build vertexmesh from arrays
8609         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8610                 dynamicvertex = true;
8611
8612         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8613         // also some drivers strongly dislike firstvertex
8614         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8615                 dynamicvertex = true;
8616
8617         rsurface.batchvertex3f = rsurface.modelvertex3f;
8618         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8619         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8620         rsurface.batchsvector3f = rsurface.modelsvector3f;
8621         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8622         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8623         rsurface.batchtvector3f = rsurface.modeltvector3f;
8624         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8625         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8626         rsurface.batchnormal3f = rsurface.modelnormal3f;
8627         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8628         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8629         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8630         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8631         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8632         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8633         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8634         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8635         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8636         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8637         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8638         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8639         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8640         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8641         rsurface.batchelement3i = rsurface.modelelement3i;
8642         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8643         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8644         rsurface.batchelement3s = rsurface.modelelement3s;
8645         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8646         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8647
8648         // if any dynamic vertex processing has to occur in software, we copy the
8649         // entire surface list together before processing to rebase the vertices
8650         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8651         //
8652         // if any gaps exist and we do not have a static vertex buffer, we have to
8653         // copy the surface list together to avoid wasting upload bandwidth on the
8654         // vertices in the gaps.
8655         //
8656         // if gaps exist and we have a static vertex buffer, we still have to
8657         // combine the index buffer ranges into one dynamic index buffer.
8658         //
8659         // in all cases we end up with data that can be drawn in one call.
8660
8661         if (!dynamicvertex)
8662         {
8663                 // static vertex data, just set pointers...
8664                 rsurface.batchgeneratedvertex = false;
8665                 // if there are gaps, we want to build a combined index buffer,
8666                 // otherwise use the original static buffer with an appropriate offset
8667                 if (gaps)
8668                 {
8669                         // build a new triangle elements array for this batch
8670                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8671                         rsurface.batchfirsttriangle = 0;
8672                         numtriangles = 0;
8673                         for (i = 0;i < texturenumsurfaces;i++)
8674                         {
8675                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8676                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8677                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8678                                 numtriangles += surfacenumtriangles;
8679                         }
8680                         rsurface.batchelement3i_indexbuffer = NULL;
8681                         rsurface.batchelement3i_bufferoffset = 0;
8682                         rsurface.batchelement3s = NULL;
8683                         rsurface.batchelement3s_indexbuffer = NULL;
8684                         rsurface.batchelement3s_bufferoffset = 0;
8685                         if (endvertex <= 65536)
8686                         {
8687                                 // make a 16bit (unsigned short) index array if possible
8688                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8689                                 for (i = 0;i < numtriangles*3;i++)
8690                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8691                         }
8692                 }
8693                 return;
8694         }
8695
8696         // something needs software processing, do it for real...
8697         // we only directly handle separate array data in this case and then
8698         // generate interleaved data if needed...
8699         rsurface.batchgeneratedvertex = true;
8700
8701         // now copy the vertex data into a combined array and make an index array
8702         // (this is what Quake3 does all the time)
8703         //if (gaps || rsurface.batchfirstvertex)
8704         {
8705                 rsurface.batchvertex3fbuffer = NULL;
8706                 rsurface.batchvertexmesh = NULL;
8707                 rsurface.batchvertexmeshbuffer = NULL;
8708                 rsurface.batchvertex3f = NULL;
8709                 rsurface.batchvertex3f_vertexbuffer = NULL;
8710                 rsurface.batchvertex3f_bufferoffset = 0;
8711                 rsurface.batchsvector3f = NULL;
8712                 rsurface.batchsvector3f_vertexbuffer = NULL;
8713                 rsurface.batchsvector3f_bufferoffset = 0;
8714                 rsurface.batchtvector3f = NULL;
8715                 rsurface.batchtvector3f_vertexbuffer = NULL;
8716                 rsurface.batchtvector3f_bufferoffset = 0;
8717                 rsurface.batchnormal3f = NULL;
8718                 rsurface.batchnormal3f_vertexbuffer = NULL;
8719                 rsurface.batchnormal3f_bufferoffset = 0;
8720                 rsurface.batchlightmapcolor4f = NULL;
8721                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8722                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8723                 rsurface.batchtexcoordtexture2f = NULL;
8724                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8725                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8726                 rsurface.batchtexcoordlightmap2f = NULL;
8727                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8728                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8729                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8730                 rsurface.batchelement3i_indexbuffer = NULL;
8731                 rsurface.batchelement3i_bufferoffset = 0;
8732                 rsurface.batchelement3s = NULL;
8733                 rsurface.batchelement3s_indexbuffer = NULL;
8734                 rsurface.batchelement3s_bufferoffset = 0;
8735                 // we'll only be setting up certain arrays as needed
8736                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8737                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8738                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8739                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8740                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8741                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8742                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8743                 {
8744                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8745                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8746                 }
8747                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8748                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8749                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8750                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8751                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8752                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8753                 numvertices = 0;
8754                 numtriangles = 0;
8755                 for (i = 0;i < texturenumsurfaces;i++)
8756                 {
8757                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8758                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8759                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8760                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8761                         // copy only the data requested
8762                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8763                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8764                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8765                         {
8766                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8767                                 {
8768                                         if (rsurface.batchvertex3f)
8769                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8770                                         else
8771                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8772                                 }
8773                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8774                                 {
8775                                         if (rsurface.modelnormal3f)
8776                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8777                                         else
8778                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8779                                 }
8780                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8781                                 {
8782                                         if (rsurface.modelsvector3f)
8783                                         {
8784                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8785                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8786                                         }
8787                                         else
8788                                         {
8789                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8790                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8791                                         }
8792                                 }
8793                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8794                                 {
8795                                         if (rsurface.modellightmapcolor4f)
8796                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8797                                         else
8798                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8799                                 }
8800                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8801                                 {
8802                                         if (rsurface.modeltexcoordtexture2f)
8803                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8804                                         else
8805                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8806                                 }
8807                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8808                                 {
8809                                         if (rsurface.modeltexcoordlightmap2f)
8810                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8811                                         else
8812                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8813                                 }
8814                         }
8815                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8816                         numvertices += surfacenumvertices;
8817                         numtriangles += surfacenumtriangles;
8818                 }
8819
8820                 // generate a 16bit index array as well if possible
8821                 // (in general, dynamic batches fit)
8822                 if (numvertices <= 65536)
8823                 {
8824                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8825                         for (i = 0;i < numtriangles*3;i++)
8826                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8827                 }
8828
8829                 // since we've copied everything, the batch now starts at 0
8830                 rsurface.batchfirstvertex = 0;
8831                 rsurface.batchnumvertices = batchnumvertices;
8832                 rsurface.batchfirsttriangle = 0;
8833                 rsurface.batchnumtriangles = batchnumtriangles;
8834         }
8835
8836         // q1bsp surfaces rendered in vertex color mode have to have colors
8837         // calculated based on lightstyles
8838         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8839         {
8840                 // generate color arrays for the surfaces in this list
8841                 int c[4];
8842                 int scale;
8843                 int size3;
8844                 const int *offsets;
8845                 const unsigned char *lm;
8846                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8847                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8848                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8849                 numvertices = 0;
8850                 for (i = 0;i < texturenumsurfaces;i++)
8851                 {
8852                         surface = texturesurfacelist[i];
8853                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8854                         surfacenumvertices = surface->num_vertices;
8855                         if (surface->lightmapinfo->samples)
8856                         {
8857                                 for (j = 0;j < surfacenumvertices;j++)
8858                                 {
8859                                         lm = surface->lightmapinfo->samples + offsets[j];
8860                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8861                                         VectorScale(lm, scale, c);
8862                                         if (surface->lightmapinfo->styles[1] != 255)
8863                                         {
8864                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8865                                                 lm += size3;
8866                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8867                                                 VectorMA(c, scale, lm, c);
8868                                                 if (surface->lightmapinfo->styles[2] != 255)
8869                                                 {
8870                                                         lm += size3;
8871                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8872                                                         VectorMA(c, scale, lm, c);
8873                                                         if (surface->lightmapinfo->styles[3] != 255)
8874                                                         {
8875                                                                 lm += size3;
8876                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8877                                                                 VectorMA(c, scale, lm, c);
8878                                                         }
8879                                                 }
8880                                         }
8881                                         c[0] >>= 7;
8882                                         c[1] >>= 7;
8883                                         c[2] >>= 7;
8884                                         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);
8885                                         numvertices++;
8886                                 }
8887                         }
8888                         else
8889                         {
8890                                 for (j = 0;j < surfacenumvertices;j++)
8891                                 {
8892                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8893                                         numvertices++;
8894                                 }
8895                         }
8896                 }
8897         }
8898
8899         // if vertices are deformed (sprite flares and things in maps, possibly
8900         // water waves, bulges and other deformations), modify the copied vertices
8901         // in place
8902         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8903         {
8904                 switch (deform->deform)
8905                 {
8906                 default:
8907                 case Q3DEFORM_PROJECTIONSHADOW:
8908                 case Q3DEFORM_TEXT0:
8909                 case Q3DEFORM_TEXT1:
8910                 case Q3DEFORM_TEXT2:
8911                 case Q3DEFORM_TEXT3:
8912                 case Q3DEFORM_TEXT4:
8913                 case Q3DEFORM_TEXT5:
8914                 case Q3DEFORM_TEXT6:
8915                 case Q3DEFORM_TEXT7:
8916                 case Q3DEFORM_NONE:
8917                         break;
8918                 case Q3DEFORM_AUTOSPRITE:
8919                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8920                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8921                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8922                         VectorNormalize(newforward);
8923                         VectorNormalize(newright);
8924                         VectorNormalize(newup);
8925 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8926 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8927 //                      rsurface.batchvertex3f_bufferoffset = 0;
8928 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8929 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8930 //                      rsurface.batchsvector3f_bufferoffset = 0;
8931 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8932 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8933 //                      rsurface.batchtvector3f_bufferoffset = 0;
8934 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8935 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8936 //                      rsurface.batchnormal3f_bufferoffset = 0;
8937                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8938                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8939                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8940                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8941                                 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);
8942                         // a single autosprite surface can contain multiple sprites...
8943                         for (j = 0;j < batchnumvertices - 3;j += 4)
8944                         {
8945                                 VectorClear(center);
8946                                 for (i = 0;i < 4;i++)
8947                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8948                                 VectorScale(center, 0.25f, center);
8949                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8950                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8951                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8952                                 for (i = 0;i < 4;i++)
8953                                 {
8954                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8955                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8956                                 }
8957                         }
8958                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8959                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8960                         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);
8961                         break;
8962                 case Q3DEFORM_AUTOSPRITE2:
8963                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8964                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8965                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8966                         VectorNormalize(newforward);
8967                         VectorNormalize(newright);
8968                         VectorNormalize(newup);
8969 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8970 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8971 //                      rsurface.batchvertex3f_bufferoffset = 0;
8972                         {
8973                                 const float *v1, *v2;
8974                                 vec3_t start, end;
8975                                 float f, l;
8976                                 struct
8977                                 {
8978                                         float length2;
8979                                         const float *v1;
8980                                         const float *v2;
8981                                 }
8982                                 shortest[2];
8983                                 memset(shortest, 0, sizeof(shortest));
8984                                 // a single autosprite surface can contain multiple sprites...
8985                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8986                                 {
8987                                         VectorClear(center);
8988                                         for (i = 0;i < 4;i++)
8989                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8990                                         VectorScale(center, 0.25f, center);
8991                                         // find the two shortest edges, then use them to define the
8992                                         // axis vectors for rotating around the central axis
8993                                         for (i = 0;i < 6;i++)
8994                                         {
8995                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8996                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8997                                                 l = VectorDistance2(v1, v2);
8998                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8999                                                 if (v1[2] != v2[2])
9000                                                         l += (1.0f / 1024.0f);
9001                                                 if (shortest[0].length2 > l || i == 0)
9002                                                 {
9003                                                         shortest[1] = shortest[0];
9004                                                         shortest[0].length2 = l;
9005                                                         shortest[0].v1 = v1;
9006                                                         shortest[0].v2 = v2;
9007                                                 }
9008                                                 else if (shortest[1].length2 > l || i == 1)
9009                                                 {
9010                                                         shortest[1].length2 = l;
9011                                                         shortest[1].v1 = v1;
9012                                                         shortest[1].v2 = v2;
9013                                                 }
9014                                         }
9015                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9016                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9017                                         // this calculates the right vector from the shortest edge
9018                                         // and the up vector from the edge midpoints
9019                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9020                                         VectorNormalize(right);
9021                                         VectorSubtract(end, start, up);
9022                                         VectorNormalize(up);
9023                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9024                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9025                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9026                                         VectorNegate(forward, forward);
9027                                         VectorReflect(forward, 0, up, forward);
9028                                         VectorNormalize(forward);
9029                                         CrossProduct(up, forward, newright);
9030                                         VectorNormalize(newright);
9031                                         // rotate the quad around the up axis vector, this is made
9032                                         // especially easy by the fact we know the quad is flat,
9033                                         // so we only have to subtract the center position and
9034                                         // measure distance along the right vector, and then
9035                                         // multiply that by the newright vector and add back the
9036                                         // center position
9037                                         // we also need to subtract the old position to undo the
9038                                         // displacement from the center, which we do with a
9039                                         // DotProduct, the subtraction/addition of center is also
9040                                         // optimized into DotProducts here
9041                                         l = DotProduct(right, center);
9042                                         for (i = 0;i < 4;i++)
9043                                         {
9044                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9045                                                 f = DotProduct(right, v1) - l;
9046                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9047                                         }
9048                                 }
9049                         }
9050                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9051                         {
9052 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9053 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9054 //                              rsurface.batchnormal3f_bufferoffset = 0;
9055                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9056                         }
9057                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9058                         {
9059 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9060 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9061 //                              rsurface.batchsvector3f_bufferoffset = 0;
9062 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9063 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9064 //                              rsurface.batchtvector3f_bufferoffset = 0;
9065                                 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);
9066                         }
9067                         break;
9068                 case Q3DEFORM_NORMAL:
9069                         // deform the normals to make reflections wavey
9070                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9071                         rsurface.batchnormal3f_vertexbuffer = NULL;
9072                         rsurface.batchnormal3f_bufferoffset = 0;
9073                         for (j = 0;j < batchnumvertices;j++)
9074                         {
9075                                 float vertex[3];
9076                                 float *normal = rsurface.batchnormal3f + 3*j;
9077                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9078                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9079                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9080                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9081                                 VectorNormalize(normal);
9082                         }
9083                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9084                         {
9085 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9086 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9087 //                              rsurface.batchsvector3f_bufferoffset = 0;
9088 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9089 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9090 //                              rsurface.batchtvector3f_bufferoffset = 0;
9091                                 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);
9092                         }
9093                         break;
9094                 case Q3DEFORM_WAVE:
9095                         // deform vertex array to make wavey water and flags and such
9096                         waveparms[0] = deform->waveparms[0];
9097                         waveparms[1] = deform->waveparms[1];
9098                         waveparms[2] = deform->waveparms[2];
9099                         waveparms[3] = deform->waveparms[3];
9100                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9101                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9102                         // this is how a divisor of vertex influence on deformation
9103                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9104                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9105 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9106 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9107 //                      rsurface.batchvertex3f_bufferoffset = 0;
9108 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9109 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9110 //                      rsurface.batchnormal3f_bufferoffset = 0;
9111                         for (j = 0;j < batchnumvertices;j++)
9112                         {
9113                                 // if the wavefunc depends on time, evaluate it per-vertex
9114                                 if (waveparms[3])
9115                                 {
9116                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9117                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9118                                 }
9119                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9120                         }
9121                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9122                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9123                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9124                         {
9125 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9126 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9127 //                              rsurface.batchsvector3f_bufferoffset = 0;
9128 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9129 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9130 //                              rsurface.batchtvector3f_bufferoffset = 0;
9131                                 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);
9132                         }
9133                         break;
9134                 case Q3DEFORM_BULGE:
9135                         // deform vertex array to make the surface have moving bulges
9136 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9137 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9138 //                      rsurface.batchvertex3f_bufferoffset = 0;
9139 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9140 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9141 //                      rsurface.batchnormal3f_bufferoffset = 0;
9142                         for (j = 0;j < batchnumvertices;j++)
9143                         {
9144                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9145                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9146                         }
9147                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9148                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9149                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9150                         {
9151 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9152 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9153 //                              rsurface.batchsvector3f_bufferoffset = 0;
9154 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9155 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9156 //                              rsurface.batchtvector3f_bufferoffset = 0;
9157                                 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);
9158                         }
9159                         break;
9160                 case Q3DEFORM_MOVE:
9161                         // deform vertex array
9162                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9163                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9164                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9165                         VectorScale(deform->parms, scale, waveparms);
9166 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9167 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9168 //                      rsurface.batchvertex3f_bufferoffset = 0;
9169                         for (j = 0;j < batchnumvertices;j++)
9170                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9171                         break;
9172                 }
9173         }
9174
9175         // generate texcoords based on the chosen texcoord source
9176         switch(rsurface.texture->tcgen.tcgen)
9177         {
9178         default:
9179         case Q3TCGEN_TEXTURE:
9180                 break;
9181         case Q3TCGEN_LIGHTMAP:
9182 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9183 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9184 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9185                 if (rsurface.batchtexcoordlightmap2f)
9186                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9187                 break;
9188         case Q3TCGEN_VECTOR:
9189 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9190 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9191 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9192                 for (j = 0;j < batchnumvertices;j++)
9193                 {
9194                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9195                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9196                 }
9197                 break;
9198         case Q3TCGEN_ENVIRONMENT:
9199                 // make environment reflections using a spheremap
9200                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9201                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9202                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9203                 for (j = 0;j < batchnumvertices;j++)
9204                 {
9205                         // identical to Q3A's method, but executed in worldspace so
9206                         // carried models can be shiny too
9207
9208                         float viewer[3], d, reflected[3], worldreflected[3];
9209
9210                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9211                         // VectorNormalize(viewer);
9212
9213                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9214
9215                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9216                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9217                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9218                         // note: this is proportinal to viewer, so we can normalize later
9219
9220                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9221                         VectorNormalize(worldreflected);
9222
9223                         // note: this sphere map only uses world x and z!
9224                         // so positive and negative y will LOOK THE SAME.
9225                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9226                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9227                 }
9228                 break;
9229         }
9230         // the only tcmod that needs software vertex processing is turbulent, so
9231         // check for it here and apply the changes if needed
9232         // and we only support that as the first one
9233         // (handling a mixture of turbulent and other tcmods would be problematic
9234         //  without punting it entirely to a software path)
9235         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9236         {
9237                 amplitude = rsurface.texture->tcmods[0].parms[1];
9238                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9239 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9240 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9241 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9242                 for (j = 0;j < batchnumvertices;j++)
9243                 {
9244                         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);
9245                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9246                 }
9247         }
9248
9249         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9250         {
9251                 // convert the modified arrays to vertex structs
9252 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9253 //              rsurface.batchvertexmeshbuffer = NULL;
9254                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9255                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9256                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9257                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9258                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9259                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9260                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9261                 {
9262                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9263                         {
9264                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9265                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9266                         }
9267                 }
9268                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9269                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9270                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9271                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9272                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9273                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9274                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9275                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9276                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9277         }
9278 }
9279
9280 void RSurf_DrawBatch(void)
9281 {
9282         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9283         // through the pipeline, killing it earlier in the pipeline would have
9284         // per-surface overhead rather than per-batch overhead, so it's best to
9285         // reject it here, before it hits glDraw.
9286         if (rsurface.batchnumtriangles == 0)
9287                 return;
9288 #if 0
9289         // batch debugging code
9290         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9291         {
9292                 int i;
9293                 int j;
9294                 int c;
9295                 const int *e;
9296                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9297                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9298                 {
9299                         c = e[i];
9300                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9301                         {
9302                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9303                                 {
9304                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9305                                                 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);
9306                                         break;
9307                                 }
9308                         }
9309                 }
9310         }
9311 #endif
9312         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);
9313 }
9314
9315 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9316 {
9317         // pick the closest matching water plane
9318         int planeindex, vertexindex, bestplaneindex = -1;
9319         float d, bestd;
9320         vec3_t vert;
9321         const float *v;
9322         r_waterstate_waterplane_t *p;
9323         qboolean prepared = false;
9324         bestd = 0;
9325         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9326         {
9327                 if(p->camera_entity != rsurface.texture->camera_entity)
9328                         continue;
9329                 d = 0;
9330                 if(!prepared)
9331                 {
9332                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9333                         prepared = true;
9334                         if(rsurface.batchnumvertices == 0)
9335                                 break;
9336                 }
9337                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9338                 {
9339                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9340                         d += fabs(PlaneDiff(vert, &p->plane));
9341                 }
9342                 if (bestd > d || bestplaneindex < 0)
9343                 {
9344                         bestd = d;
9345                         bestplaneindex = planeindex;
9346                 }
9347         }
9348         return bestplaneindex;
9349         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9350         // this situation though, as it might be better to render single larger
9351         // batches with useless stuff (backface culled for example) than to
9352         // render multiple smaller batches
9353 }
9354
9355 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9356 {
9357         int i;
9358         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9359         rsurface.passcolor4f_vertexbuffer = 0;
9360         rsurface.passcolor4f_bufferoffset = 0;
9361         for (i = 0;i < rsurface.batchnumvertices;i++)
9362                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9363 }
9364
9365 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9366 {
9367         int i;
9368         float f;
9369         const float *v;
9370         const float *c;
9371         float *c2;
9372         if (rsurface.passcolor4f)
9373         {
9374                 // generate color arrays
9375                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9376                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9377                 rsurface.passcolor4f_vertexbuffer = 0;
9378                 rsurface.passcolor4f_bufferoffset = 0;
9379                 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)
9380                 {
9381                         f = RSurf_FogVertex(v);
9382                         c2[0] = c[0] * f;
9383                         c2[1] = c[1] * f;
9384                         c2[2] = c[2] * f;
9385                         c2[3] = c[3];
9386                 }
9387         }
9388         else
9389         {
9390                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9391                 rsurface.passcolor4f_vertexbuffer = 0;
9392                 rsurface.passcolor4f_bufferoffset = 0;
9393                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9394                 {
9395                         f = RSurf_FogVertex(v);
9396                         c2[0] = f;
9397                         c2[1] = f;
9398                         c2[2] = f;
9399                         c2[3] = 1;
9400                 }
9401         }
9402 }
9403
9404 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9405 {
9406         int i;
9407         float f;
9408         const float *v;
9409         const float *c;
9410         float *c2;
9411         if (!rsurface.passcolor4f)
9412                 return;
9413         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9414         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9415         rsurface.passcolor4f_vertexbuffer = 0;
9416         rsurface.passcolor4f_bufferoffset = 0;
9417         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)
9418         {
9419                 f = RSurf_FogVertex(v);
9420                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9421                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9422                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9423                 c2[3] = c[3];
9424         }
9425 }
9426
9427 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9428 {
9429         int i;
9430         const float *c;
9431         float *c2;
9432         if (!rsurface.passcolor4f)
9433                 return;
9434         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9435         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9436         rsurface.passcolor4f_vertexbuffer = 0;
9437         rsurface.passcolor4f_bufferoffset = 0;
9438         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9439         {
9440                 c2[0] = c[0] * r;
9441                 c2[1] = c[1] * g;
9442                 c2[2] = c[2] * b;
9443                 c2[3] = c[3] * a;
9444         }
9445 }
9446
9447 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9448 {
9449         int i;
9450         const float *c;
9451         float *c2;
9452         if (!rsurface.passcolor4f)
9453                 return;
9454         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9455         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9456         rsurface.passcolor4f_vertexbuffer = 0;
9457         rsurface.passcolor4f_bufferoffset = 0;
9458         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9459         {
9460                 c2[0] = c[0] + r_refdef.scene.ambient;
9461                 c2[1] = c[1] + r_refdef.scene.ambient;
9462                 c2[2] = c[2] + r_refdef.scene.ambient;
9463                 c2[3] = c[3];
9464         }
9465 }
9466
9467 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9468 {
9469         // TODO: optimize
9470         rsurface.passcolor4f = NULL;
9471         rsurface.passcolor4f_vertexbuffer = 0;
9472         rsurface.passcolor4f_bufferoffset = 0;
9473         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9474         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9475         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9476         GL_Color(r, g, b, a);
9477         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9478         RSurf_DrawBatch();
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9482 {
9483         // TODO: optimize applyfog && applycolor case
9484         // just apply fog if necessary, and tint the fog color array if necessary
9485         rsurface.passcolor4f = NULL;
9486         rsurface.passcolor4f_vertexbuffer = 0;
9487         rsurface.passcolor4f_bufferoffset = 0;
9488         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9489         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9490         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9491         GL_Color(r, g, b, a);
9492         RSurf_DrawBatch();
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9496 {
9497         // TODO: optimize
9498         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9499         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9500         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9501         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9502         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9503         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9504         GL_Color(r, g, b, a);
9505         RSurf_DrawBatch();
9506 }
9507
9508 static void RSurf_DrawBatch_GL11_ClampColor(void)
9509 {
9510         int i;
9511         const float *c1;
9512         float *c2;
9513         if (!rsurface.passcolor4f)
9514                 return;
9515         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9516         {
9517                 c2[0] = bound(0.0f, c1[0], 1.0f);
9518                 c2[1] = bound(0.0f, c1[1], 1.0f);
9519                 c2[2] = bound(0.0f, c1[2], 1.0f);
9520                 c2[3] = bound(0.0f, c1[3], 1.0f);
9521         }
9522 }
9523
9524 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9525 {
9526         int i;
9527         float f;
9528         const float *v;
9529         const float *n;
9530         float *c;
9531         //vec3_t eyedir;
9532
9533         // fake shading
9534         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9535         rsurface.passcolor4f_vertexbuffer = 0;
9536         rsurface.passcolor4f_bufferoffset = 0;
9537         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)
9538         {
9539                 f = -DotProduct(r_refdef.view.forward, n);
9540                 f = max(0, f);
9541                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9542                 f *= r_refdef.lightmapintensity;
9543                 Vector4Set(c, f, f, f, 1);
9544         }
9545 }
9546
9547 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9548 {
9549         RSurf_DrawBatch_GL11_ApplyFakeLight();
9550         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9551         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9552         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9553         GL_Color(r, g, b, a);
9554         RSurf_DrawBatch();
9555 }
9556
9557 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9558 {
9559         int i;
9560         float f;
9561         float alpha;
9562         const float *v;
9563         const float *n;
9564         float *c;
9565         vec3_t ambientcolor;
9566         vec3_t diffusecolor;
9567         vec3_t lightdir;
9568         // TODO: optimize
9569         // model lighting
9570         VectorCopy(rsurface.modellight_lightdir, lightdir);
9571         f = 0.5f * r_refdef.lightmapintensity;
9572         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9573         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9574         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9575         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9576         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9577         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9578         alpha = *a;
9579         if (VectorLength2(diffusecolor) > 0)
9580         {
9581                 // q3-style directional shading
9582                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9583                 rsurface.passcolor4f_vertexbuffer = 0;
9584                 rsurface.passcolor4f_bufferoffset = 0;
9585                 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)
9586                 {
9587                         if ((f = DotProduct(n, lightdir)) > 0)
9588                                 VectorMA(ambientcolor, f, diffusecolor, c);
9589                         else
9590                                 VectorCopy(ambientcolor, c);
9591                         c[3] = alpha;
9592                 }
9593                 *r = 1;
9594                 *g = 1;
9595                 *b = 1;
9596                 *a = 1;
9597                 *applycolor = false;
9598         }
9599         else
9600         {
9601                 *r = ambientcolor[0];
9602                 *g = ambientcolor[1];
9603                 *b = ambientcolor[2];
9604                 rsurface.passcolor4f = NULL;
9605                 rsurface.passcolor4f_vertexbuffer = 0;
9606                 rsurface.passcolor4f_bufferoffset = 0;
9607         }
9608 }
9609
9610 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9611 {
9612         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9613         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9614         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9615         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9616         GL_Color(r, g, b, a);
9617         RSurf_DrawBatch();
9618 }
9619
9620 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9621 {
9622         int i;
9623         float f;
9624         const float *v;
9625         float *c;
9626
9627         // fake shading
9628         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9629         rsurface.passcolor4f_vertexbuffer = 0;
9630         rsurface.passcolor4f_bufferoffset = 0;
9631
9632         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9633         {
9634                 f = 1 - RSurf_FogVertex(v);
9635                 c[0] = r;
9636                 c[1] = g;
9637                 c[2] = b;
9638                 c[3] = f * a;
9639         }
9640 }
9641
9642 void RSurf_SetupDepthAndCulling(void)
9643 {
9644         // submodels are biased to avoid z-fighting with world surfaces that they
9645         // may be exactly overlapping (avoids z-fighting artifacts on certain
9646         // doors and things in Quake maps)
9647         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9648         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9649         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9650         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9651 }
9652
9653 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9654 {
9655         // transparent sky would be ridiculous
9656         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9657                 return;
9658         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9659         skyrenderlater = true;
9660         RSurf_SetupDepthAndCulling();
9661         GL_DepthMask(true);
9662         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9663         // skymasking on them, and Quake3 never did sky masking (unlike
9664         // software Quake and software Quake2), so disable the sky masking
9665         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9666         // and skymasking also looks very bad when noclipping outside the
9667         // level, so don't use it then either.
9668         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9669         {
9670                 R_Mesh_ResetTextureState();
9671                 if (skyrendermasked)
9672                 {
9673                         R_SetupShader_DepthOrShadow(false);
9674                         // depth-only (masking)
9675                         GL_ColorMask(0,0,0,0);
9676                         // just to make sure that braindead drivers don't draw
9677                         // anything despite that colormask...
9678                         GL_BlendFunc(GL_ZERO, GL_ONE);
9679                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9680                         if (rsurface.batchvertex3fbuffer)
9681                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9682                         else
9683                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9684                 }
9685                 else
9686                 {
9687                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9688                         // fog sky
9689                         GL_BlendFunc(GL_ONE, GL_ZERO);
9690                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9691                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9692                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9693                 }
9694                 RSurf_DrawBatch();
9695                 if (skyrendermasked)
9696                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9697         }
9698         R_Mesh_ResetTextureState();
9699         GL_Color(1, 1, 1, 1);
9700 }
9701
9702 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9703 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9704 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9705 {
9706         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9707                 return;
9708         if (prepass)
9709         {
9710                 // render screenspace normalmap to texture
9711                 GL_DepthMask(true);
9712                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9713                 RSurf_DrawBatch();
9714         }
9715
9716         // bind lightmap texture
9717
9718         // water/refraction/reflection/camera surfaces have to be handled specially
9719         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9720         {
9721                 int start, end, startplaneindex;
9722                 for (start = 0;start < texturenumsurfaces;start = end)
9723                 {
9724                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9725                         if(startplaneindex < 0)
9726                         {
9727                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9728                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9729                                 end = start + 1;
9730                                 continue;
9731                         }
9732                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9733                                 ;
9734                         // now that we have a batch using the same planeindex, render it
9735                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9736                         {
9737                                 // render water or distortion background
9738                                 GL_DepthMask(true);
9739                                 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);
9740                                 RSurf_DrawBatch();
9741                                 // blend surface on top
9742                                 GL_DepthMask(false);
9743                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9744                                 RSurf_DrawBatch();
9745                         }
9746                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9747                         {
9748                                 // render surface with reflection texture as input
9749                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9750                                 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);
9751                                 RSurf_DrawBatch();
9752                         }
9753                 }
9754                 return;
9755         }
9756
9757         // render surface batch normally
9758         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9759         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);
9760         RSurf_DrawBatch();
9761 }
9762
9763 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9764 {
9765         // OpenGL 1.3 path - anything not completely ancient
9766         qboolean applycolor;
9767         qboolean applyfog;
9768         int layerindex;
9769         const texturelayer_t *layer;
9770         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);
9771         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9772
9773         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9774         {
9775                 vec4_t layercolor;
9776                 int layertexrgbscale;
9777                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9778                 {
9779                         if (layerindex == 0)
9780                                 GL_AlphaTest(true);
9781                         else
9782                         {
9783                                 GL_AlphaTest(false);
9784                                 GL_DepthFunc(GL_EQUAL);
9785                         }
9786                 }
9787                 GL_DepthMask(layer->depthmask && writedepth);
9788                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9789                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9790                 {
9791                         layertexrgbscale = 4;
9792                         VectorScale(layer->color, 0.25f, layercolor);
9793                 }
9794                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9795                 {
9796                         layertexrgbscale = 2;
9797                         VectorScale(layer->color, 0.5f, layercolor);
9798                 }
9799                 else
9800                 {
9801                         layertexrgbscale = 1;
9802                         VectorScale(layer->color, 1.0f, layercolor);
9803                 }
9804                 layercolor[3] = layer->color[3];
9805                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9806                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9807                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9808                 switch (layer->type)
9809                 {
9810                 case TEXTURELAYERTYPE_LITTEXTURE:
9811                         // single-pass lightmapped texture with 2x rgbscale
9812                         R_Mesh_TexBind(0, r_texture_white);
9813                         R_Mesh_TexMatrix(0, NULL);
9814                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9815                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9816                         R_Mesh_TexBind(1, layer->texture);
9817                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9818                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9819                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9820                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9821                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9822                         else if (FAKELIGHT_ENABLED)
9823                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9824                         else if (rsurface.uselightmaptexture)
9825                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9826                         else
9827                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9828                         break;
9829                 case TEXTURELAYERTYPE_TEXTURE:
9830                         // singletexture unlit texture with transparency support
9831                         R_Mesh_TexBind(0, layer->texture);
9832                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9833                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9834                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9835                         R_Mesh_TexBind(1, 0);
9836                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9837                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9838                         break;
9839                 case TEXTURELAYERTYPE_FOG:
9840                         // singletexture fogging
9841                         if (layer->texture)
9842                         {
9843                                 R_Mesh_TexBind(0, layer->texture);
9844                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9845                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9846                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9847                         }
9848                         else
9849                         {
9850                                 R_Mesh_TexBind(0, 0);
9851                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9852                         }
9853                         R_Mesh_TexBind(1, 0);
9854                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9855                         // generate a color array for the fog pass
9856                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9857                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9858                         RSurf_DrawBatch();
9859                         break;
9860                 default:
9861                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9862                 }
9863         }
9864         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9865         {
9866                 GL_DepthFunc(GL_LEQUAL);
9867                 GL_AlphaTest(false);
9868         }
9869 }
9870
9871 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9872 {
9873         // OpenGL 1.1 - crusty old voodoo path
9874         qboolean applyfog;
9875         int layerindex;
9876         const texturelayer_t *layer;
9877         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);
9878         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9879
9880         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9881         {
9882                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9883                 {
9884                         if (layerindex == 0)
9885                                 GL_AlphaTest(true);
9886                         else
9887                         {
9888                                 GL_AlphaTest(false);
9889                                 GL_DepthFunc(GL_EQUAL);
9890                         }
9891                 }
9892                 GL_DepthMask(layer->depthmask && writedepth);
9893                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9894                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9895                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9896                 switch (layer->type)
9897                 {
9898                 case TEXTURELAYERTYPE_LITTEXTURE:
9899                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9900                         {
9901                                 // two-pass lit texture with 2x rgbscale
9902                                 // first the lightmap pass
9903                                 R_Mesh_TexBind(0, r_texture_white);
9904                                 R_Mesh_TexMatrix(0, NULL);
9905                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9906                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9907                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9908                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9909                                 else if (FAKELIGHT_ENABLED)
9910                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9911                                 else if (rsurface.uselightmaptexture)
9912                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9913                                 else
9914                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9915                                 // then apply the texture to it
9916                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9917                                 R_Mesh_TexBind(0, layer->texture);
9918                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9919                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9920                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9921                                 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);
9922                         }
9923                         else
9924                         {
9925                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9926                                 R_Mesh_TexBind(0, layer->texture);
9927                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9928                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9929                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9930                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9931                                         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);
9932                                 else
9933                                         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);
9934                         }
9935                         break;
9936                 case TEXTURELAYERTYPE_TEXTURE:
9937                         // singletexture unlit texture with transparency support
9938                         R_Mesh_TexBind(0, layer->texture);
9939                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9940                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9941                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9942                         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);
9943                         break;
9944                 case TEXTURELAYERTYPE_FOG:
9945                         // singletexture fogging
9946                         if (layer->texture)
9947                         {
9948                                 R_Mesh_TexBind(0, layer->texture);
9949                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9950                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9951                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9952                         }
9953                         else
9954                         {
9955                                 R_Mesh_TexBind(0, 0);
9956                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9957                         }
9958                         // generate a color array for the fog pass
9959                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9960                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9961                         RSurf_DrawBatch();
9962                         break;
9963                 default:
9964                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9965                 }
9966         }
9967         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9968         {
9969                 GL_DepthFunc(GL_LEQUAL);
9970                 GL_AlphaTest(false);
9971         }
9972 }
9973
9974 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9975 {
9976         int vi;
9977         int j;
9978         r_vertexgeneric_t *batchvertex;
9979         float c[4];
9980
9981 //      R_Mesh_ResetTextureState();
9982         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9983
9984         if(rsurface.texture && rsurface.texture->currentskinframe)
9985         {
9986                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9987                 c[3] *= rsurface.texture->currentalpha;
9988         }
9989         else
9990         {
9991                 c[0] = 1;
9992                 c[1] = 0;
9993                 c[2] = 1;
9994                 c[3] = 1;
9995         }
9996
9997         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9998         {
9999                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10000                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10001                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10002         }
10003
10004         // brighten it up (as texture value 127 means "unlit")
10005         c[0] *= 2 * r_refdef.view.colorscale;
10006         c[1] *= 2 * r_refdef.view.colorscale;
10007         c[2] *= 2 * r_refdef.view.colorscale;
10008
10009         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10010                 c[3] *= r_wateralpha.value;
10011
10012         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10013         {
10014                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10015                 GL_DepthMask(false);
10016         }
10017         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10018         {
10019                 GL_BlendFunc(GL_ONE, GL_ONE);
10020                 GL_DepthMask(false);
10021         }
10022         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10023         {
10024                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10025                 GL_DepthMask(false);
10026         }
10027         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10028         {
10029                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10030                 GL_DepthMask(false);
10031         }
10032         else
10033         {
10034                 GL_BlendFunc(GL_ONE, GL_ZERO);
10035                 GL_DepthMask(writedepth);
10036         }
10037
10038         if (r_showsurfaces.integer == 3)
10039         {
10040                 rsurface.passcolor4f = NULL;
10041
10042                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10043                 {
10044                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10045
10046                         rsurface.passcolor4f = NULL;
10047                         rsurface.passcolor4f_vertexbuffer = 0;
10048                         rsurface.passcolor4f_bufferoffset = 0;
10049                 }
10050                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10051                 {
10052                         qboolean applycolor = true;
10053                         float one = 1.0;
10054
10055                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10056
10057                         r_refdef.lightmapintensity = 1;
10058                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10059                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10060                 }
10061                 else if (FAKELIGHT_ENABLED)
10062                 {
10063                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10064
10065                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10066                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10067                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10068                 }
10069                 else
10070                 {
10071                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10072
10073                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10074                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10075                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10076                 }
10077
10078                 if(!rsurface.passcolor4f)
10079                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10080
10081                 RSurf_DrawBatch_GL11_ApplyAmbient();
10082                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10083                 if(r_refdef.fogenabled)
10084                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10085                 RSurf_DrawBatch_GL11_ClampColor();
10086
10087                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10088                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10089                 RSurf_DrawBatch();
10090         }
10091         else if (!r_refdef.view.showdebug)
10092         {
10093                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10094                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10095                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10096                 {
10097                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10098                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10099                 }
10100                 R_Mesh_PrepareVertices_Generic_Unlock();
10101                 RSurf_DrawBatch();
10102         }
10103         else if (r_showsurfaces.integer == 4)
10104         {
10105                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10106                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10107                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10108                 {
10109                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10110                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10111                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10112                 }
10113                 R_Mesh_PrepareVertices_Generic_Unlock();
10114                 RSurf_DrawBatch();
10115         }
10116         else if (r_showsurfaces.integer == 2)
10117         {
10118                 const int *e;
10119                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10120                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10121                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10122                 {
10123                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10124                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10125                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10126                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10127                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10128                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10129                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10130                 }
10131                 R_Mesh_PrepareVertices_Generic_Unlock();
10132                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10133         }
10134         else
10135         {
10136                 int texturesurfaceindex;
10137                 int k;
10138                 const msurface_t *surface;
10139                 float surfacecolor4f[4];
10140                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10141                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10142                 vi = 0;
10143                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10144                 {
10145                         surface = texturesurfacelist[texturesurfaceindex];
10146                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10147                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10148                         for (j = 0;j < surface->num_vertices;j++)
10149                         {
10150                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10151                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10152                                 vi++;
10153                         }
10154                 }
10155                 R_Mesh_PrepareVertices_Generic_Unlock();
10156                 RSurf_DrawBatch();
10157         }
10158 }
10159
10160 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10161 {
10162         CHECKGLERROR
10163         RSurf_SetupDepthAndCulling();
10164         if (r_showsurfaces.integer)
10165         {
10166                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10167                 return;
10168         }
10169         switch (vid.renderpath)
10170         {
10171         case RENDERPATH_GL20:
10172         case RENDERPATH_D3D9:
10173         case RENDERPATH_D3D10:
10174         case RENDERPATH_D3D11:
10175         case RENDERPATH_SOFT:
10176         case RENDERPATH_GLES2:
10177                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10178                 break;
10179         case RENDERPATH_GL13:
10180         case RENDERPATH_GLES1:
10181                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10182                 break;
10183         case RENDERPATH_GL11:
10184                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10185                 break;
10186         }
10187         CHECKGLERROR
10188 }
10189
10190 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10191 {
10192         CHECKGLERROR
10193         RSurf_SetupDepthAndCulling();
10194         if (r_showsurfaces.integer)
10195         {
10196                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10197                 return;
10198         }
10199         switch (vid.renderpath)
10200         {
10201         case RENDERPATH_GL20:
10202         case RENDERPATH_D3D9:
10203         case RENDERPATH_D3D10:
10204         case RENDERPATH_D3D11:
10205         case RENDERPATH_SOFT:
10206         case RENDERPATH_GLES2:
10207                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10208                 break;
10209         case RENDERPATH_GL13:
10210         case RENDERPATH_GLES1:
10211                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10212                 break;
10213         case RENDERPATH_GL11:
10214                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10215                 break;
10216         }
10217         CHECKGLERROR
10218 }
10219
10220 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10221 {
10222         int i, j;
10223         int texturenumsurfaces, endsurface;
10224         texture_t *texture;
10225         const msurface_t *surface;
10226         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10227
10228         // if the model is static it doesn't matter what value we give for
10229         // wantnormals and wanttangents, so this logic uses only rules applicable
10230         // to a model, knowing that they are meaningless otherwise
10231         if (ent == r_refdef.scene.worldentity)
10232                 RSurf_ActiveWorldEntity();
10233         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10234                 RSurf_ActiveModelEntity(ent, false, false, false);
10235         else
10236         {
10237                 switch (vid.renderpath)
10238                 {
10239                 case RENDERPATH_GL20:
10240                 case RENDERPATH_D3D9:
10241                 case RENDERPATH_D3D10:
10242                 case RENDERPATH_D3D11:
10243                 case RENDERPATH_SOFT:
10244                 case RENDERPATH_GLES2:
10245                         RSurf_ActiveModelEntity(ent, true, true, false);
10246                         break;
10247                 case RENDERPATH_GL11:
10248                 case RENDERPATH_GL13:
10249                 case RENDERPATH_GLES1:
10250                         RSurf_ActiveModelEntity(ent, true, false, false);
10251                         break;
10252                 }
10253         }
10254
10255         if (r_transparentdepthmasking.integer)
10256         {
10257                 qboolean setup = false;
10258                 for (i = 0;i < numsurfaces;i = j)
10259                 {
10260                         j = i + 1;
10261                         surface = rsurface.modelsurfaces + surfacelist[i];
10262                         texture = surface->texture;
10263                         rsurface.texture = R_GetCurrentTexture(texture);
10264                         rsurface.lightmaptexture = NULL;
10265                         rsurface.deluxemaptexture = NULL;
10266                         rsurface.uselightmaptexture = false;
10267                         // scan ahead until we find a different texture
10268                         endsurface = min(i + 1024, numsurfaces);
10269                         texturenumsurfaces = 0;
10270                         texturesurfacelist[texturenumsurfaces++] = surface;
10271                         for (;j < endsurface;j++)
10272                         {
10273                                 surface = rsurface.modelsurfaces + surfacelist[j];
10274                                 if (texture != surface->texture)
10275                                         break;
10276                                 texturesurfacelist[texturenumsurfaces++] = surface;
10277                         }
10278                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10279                                 continue;
10280                         // render the range of surfaces as depth
10281                         if (!setup)
10282                         {
10283                                 setup = true;
10284                                 GL_ColorMask(0,0,0,0);
10285                                 GL_Color(1,1,1,1);
10286                                 GL_DepthTest(true);
10287                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10288                                 GL_DepthMask(true);
10289 //                              R_Mesh_ResetTextureState();
10290                                 R_SetupShader_DepthOrShadow(false);
10291                         }
10292                         RSurf_SetupDepthAndCulling();
10293                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10294                         if (rsurface.batchvertex3fbuffer)
10295                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10296                         else
10297                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10298                         RSurf_DrawBatch();
10299                 }
10300                 if (setup)
10301                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10302         }
10303
10304         for (i = 0;i < numsurfaces;i = j)
10305         {
10306                 j = i + 1;
10307                 surface = rsurface.modelsurfaces + surfacelist[i];
10308                 texture = surface->texture;
10309                 rsurface.texture = R_GetCurrentTexture(texture);
10310                 // scan ahead until we find a different texture
10311                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10312                 texturenumsurfaces = 0;
10313                 texturesurfacelist[texturenumsurfaces++] = surface;
10314                 if(FAKELIGHT_ENABLED)
10315                 {
10316                         rsurface.lightmaptexture = NULL;
10317                         rsurface.deluxemaptexture = NULL;
10318                         rsurface.uselightmaptexture = false;
10319                         for (;j < endsurface;j++)
10320                         {
10321                                 surface = rsurface.modelsurfaces + surfacelist[j];
10322                                 if (texture != surface->texture)
10323                                         break;
10324                                 texturesurfacelist[texturenumsurfaces++] = surface;
10325                         }
10326                 }
10327                 else
10328                 {
10329                         rsurface.lightmaptexture = surface->lightmaptexture;
10330                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10331                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10332                         for (;j < endsurface;j++)
10333                         {
10334                                 surface = rsurface.modelsurfaces + surfacelist[j];
10335                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10336                                         break;
10337                                 texturesurfacelist[texturenumsurfaces++] = surface;
10338                         }
10339                 }
10340                 // render the range of surfaces
10341                 if (ent == r_refdef.scene.worldentity)
10342                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10343                 else
10344                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10345         }
10346         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10347 }
10348
10349 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10350 {
10351         // transparent surfaces get pushed off into the transparent queue
10352         int surfacelistindex;
10353         const msurface_t *surface;
10354         vec3_t tempcenter, center;
10355         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10356         {
10357                 surface = texturesurfacelist[surfacelistindex];
10358                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10359                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10360                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10361                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10362                 if (queueentity->transparent_offset) // transparent offset
10363                 {
10364                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10365                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10366                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10367                 }
10368                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10369         }
10370 }
10371
10372 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10373 {
10374         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10375                 return;
10376         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10377                 return;
10378         RSurf_SetupDepthAndCulling();
10379         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10380         if (rsurface.batchvertex3fbuffer)
10381                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10382         else
10383                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10384         RSurf_DrawBatch();
10385 }
10386
10387 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10388 {
10389         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10390         CHECKGLERROR
10391         if (depthonly)
10392                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10393         else if (prepass)
10394         {
10395                 if (!rsurface.texture->currentnumlayers)
10396                         return;
10397                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10398                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10399                 else
10400                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10401         }
10402         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10403                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10404         else if (!rsurface.texture->currentnumlayers)
10405                 return;
10406         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10407         {
10408                 // in the deferred case, transparent surfaces were queued during prepass
10409                 if (!r_shadow_usingdeferredprepass)
10410                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10411         }
10412         else
10413         {
10414                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10415                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10416         }
10417         CHECKGLERROR
10418 }
10419
10420 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10421 {
10422         int i, j;
10423         texture_t *texture;
10424         R_FrameData_SetMark();
10425         // break the surface list down into batches by texture and use of lightmapping
10426         for (i = 0;i < numsurfaces;i = j)
10427         {
10428                 j = i + 1;
10429                 // texture is the base texture pointer, rsurface.texture is the
10430                 // current frame/skin the texture is directing us to use (for example
10431                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10432                 // use skin 1 instead)
10433                 texture = surfacelist[i]->texture;
10434                 rsurface.texture = R_GetCurrentTexture(texture);
10435                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10436                 {
10437                         // if this texture is not the kind we want, skip ahead to the next one
10438                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10439                                 ;
10440                         continue;
10441                 }
10442                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10443                 {
10444                         rsurface.lightmaptexture = NULL;
10445                         rsurface.deluxemaptexture = NULL;
10446                         rsurface.uselightmaptexture = false;
10447                         // simply scan ahead until we find a different texture or lightmap state
10448                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10449                                 ;
10450                 }
10451                 else
10452                 {
10453                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10454                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10455                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10456                         // simply scan ahead until we find a different texture or lightmap state
10457                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10458                                 ;
10459                 }
10460                 // render the range of surfaces
10461                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10462         }
10463         R_FrameData_ReturnToMark();
10464 }
10465
10466 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10467 {
10468         CHECKGLERROR
10469         if (depthonly)
10470                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10471         else if (prepass)
10472         {
10473                 if (!rsurface.texture->currentnumlayers)
10474                         return;
10475                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10476                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10477                 else
10478                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10479         }
10480         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10481                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10482         else if (!rsurface.texture->currentnumlayers)
10483                 return;
10484         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10485         {
10486                 // in the deferred case, transparent surfaces were queued during prepass
10487                 if (!r_shadow_usingdeferredprepass)
10488                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10489         }
10490         else
10491         {
10492                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10493                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10494         }
10495         CHECKGLERROR
10496 }
10497
10498 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10499 {
10500         int i, j;
10501         texture_t *texture;
10502         R_FrameData_SetMark();
10503         // break the surface list down into batches by texture and use of lightmapping
10504         for (i = 0;i < numsurfaces;i = j)
10505         {
10506                 j = i + 1;
10507                 // texture is the base texture pointer, rsurface.texture is the
10508                 // current frame/skin the texture is directing us to use (for example
10509                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10510                 // use skin 1 instead)
10511                 texture = surfacelist[i]->texture;
10512                 rsurface.texture = R_GetCurrentTexture(texture);
10513                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10514                 {
10515                         // if this texture is not the kind we want, skip ahead to the next one
10516                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10517                                 ;
10518                         continue;
10519                 }
10520                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10521                 {
10522                         rsurface.lightmaptexture = NULL;
10523                         rsurface.deluxemaptexture = NULL;
10524                         rsurface.uselightmaptexture = false;
10525                         // simply scan ahead until we find a different texture or lightmap state
10526                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10527                                 ;
10528                 }
10529                 else
10530                 {
10531                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10532                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10533                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10534                         // simply scan ahead until we find a different texture or lightmap state
10535                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10536                                 ;
10537                 }
10538                 // render the range of surfaces
10539                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10540         }
10541         R_FrameData_ReturnToMark();
10542 }
10543
10544 float locboxvertex3f[6*4*3] =
10545 {
10546         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10547         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10548         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10549         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10550         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10551         1,0,0, 0,0,0, 0,1,0, 1,1,0
10552 };
10553
10554 unsigned short locboxelements[6*2*3] =
10555 {
10556          0, 1, 2, 0, 2, 3,
10557          4, 5, 6, 4, 6, 7,
10558          8, 9,10, 8,10,11,
10559         12,13,14, 12,14,15,
10560         16,17,18, 16,18,19,
10561         20,21,22, 20,22,23
10562 };
10563
10564 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10565 {
10566         int i, j;
10567         cl_locnode_t *loc = (cl_locnode_t *)ent;
10568         vec3_t mins, size;
10569         float vertex3f[6*4*3];
10570         CHECKGLERROR
10571         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10572         GL_DepthMask(false);
10573         GL_DepthRange(0, 1);
10574         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10575         GL_DepthTest(true);
10576         GL_CullFace(GL_NONE);
10577         R_EntityMatrix(&identitymatrix);
10578
10579 //      R_Mesh_ResetTextureState();
10580
10581         i = surfacelist[0];
10582         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10583                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10584                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10585                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10586
10587         if (VectorCompare(loc->mins, loc->maxs))
10588         {
10589                 VectorSet(size, 2, 2, 2);
10590                 VectorMA(loc->mins, -0.5f, size, mins);
10591         }
10592         else
10593         {
10594                 VectorCopy(loc->mins, mins);
10595                 VectorSubtract(loc->maxs, loc->mins, size);
10596         }
10597
10598         for (i = 0;i < 6*4*3;)
10599                 for (j = 0;j < 3;j++, i++)
10600                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10601
10602         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10603         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10604         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10605 }
10606
10607 void R_DrawLocs(void)
10608 {
10609         int index;
10610         cl_locnode_t *loc, *nearestloc;
10611         vec3_t center;
10612         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10613         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10614         {
10615                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10616                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10617         }
10618 }
10619
10620 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10621 {
10622         if (decalsystem->decals)
10623                 Mem_Free(decalsystem->decals);
10624         memset(decalsystem, 0, sizeof(*decalsystem));
10625 }
10626
10627 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)
10628 {
10629         tridecal_t *decal;
10630         tridecal_t *decals;
10631         int i;
10632
10633         // expand or initialize the system
10634         if (decalsystem->maxdecals <= decalsystem->numdecals)
10635         {
10636                 decalsystem_t old = *decalsystem;
10637                 qboolean useshortelements;
10638                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10639                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10640                 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)));
10641                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10642                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10643                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10644                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10645                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10646                 if (decalsystem->numdecals)
10647                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10648                 if (old.decals)
10649                         Mem_Free(old.decals);
10650                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10651                         decalsystem->element3i[i] = i;
10652                 if (useshortelements)
10653                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10654                                 decalsystem->element3s[i] = i;
10655         }
10656
10657         // grab a decal and search for another free slot for the next one
10658         decals = decalsystem->decals;
10659         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10660         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10661                 ;
10662         decalsystem->freedecal = i;
10663         if (decalsystem->numdecals <= i)
10664                 decalsystem->numdecals = i + 1;
10665
10666         // initialize the decal
10667         decal->lived = 0;
10668         decal->triangleindex = triangleindex;
10669         decal->surfaceindex = surfaceindex;
10670         decal->decalsequence = decalsequence;
10671         decal->color4f[0][0] = c0[0];
10672         decal->color4f[0][1] = c0[1];
10673         decal->color4f[0][2] = c0[2];
10674         decal->color4f[0][3] = 1;
10675         decal->color4f[1][0] = c1[0];
10676         decal->color4f[1][1] = c1[1];
10677         decal->color4f[1][2] = c1[2];
10678         decal->color4f[1][3] = 1;
10679         decal->color4f[2][0] = c2[0];
10680         decal->color4f[2][1] = c2[1];
10681         decal->color4f[2][2] = c2[2];
10682         decal->color4f[2][3] = 1;
10683         decal->vertex3f[0][0] = v0[0];
10684         decal->vertex3f[0][1] = v0[1];
10685         decal->vertex3f[0][2] = v0[2];
10686         decal->vertex3f[1][0] = v1[0];
10687         decal->vertex3f[1][1] = v1[1];
10688         decal->vertex3f[1][2] = v1[2];
10689         decal->vertex3f[2][0] = v2[0];
10690         decal->vertex3f[2][1] = v2[1];
10691         decal->vertex3f[2][2] = v2[2];
10692         decal->texcoord2f[0][0] = t0[0];
10693         decal->texcoord2f[0][1] = t0[1];
10694         decal->texcoord2f[1][0] = t1[0];
10695         decal->texcoord2f[1][1] = t1[1];
10696         decal->texcoord2f[2][0] = t2[0];
10697         decal->texcoord2f[2][1] = t2[1];
10698         TriangleNormal(v0, v1, v2, decal->plane);
10699         VectorNormalize(decal->plane);
10700         decal->plane[3] = DotProduct(v0, decal->plane);
10701 }
10702
10703 extern cvar_t cl_decals_bias;
10704 extern cvar_t cl_decals_models;
10705 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10706 // baseparms, parms, temps
10707 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)
10708 {
10709         int cornerindex;
10710         int index;
10711         float v[9][3];
10712         const float *vertex3f;
10713         const float *normal3f;
10714         int numpoints;
10715         float points[2][9][3];
10716         float temp[3];
10717         float tc[9][2];
10718         float f;
10719         float c[9][4];
10720         const int *e;
10721
10722         e = rsurface.modelelement3i + 3*triangleindex;
10723
10724         vertex3f = rsurface.modelvertex3f;
10725         normal3f = rsurface.modelnormal3f;
10726
10727         if (normal3f)
10728         {
10729                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10730                 {
10731                         index = 3*e[cornerindex];
10732                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10733                 }
10734         }
10735         else
10736         {
10737                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10738                 {
10739                         index = 3*e[cornerindex];
10740                         VectorCopy(vertex3f + index, v[cornerindex]);
10741                 }
10742         }
10743
10744         // cull backfaces
10745         //TriangleNormal(v[0], v[1], v[2], normal);
10746         //if (DotProduct(normal, localnormal) < 0.0f)
10747         //      continue;
10748         // clip by each of the box planes formed from the projection matrix
10749         // if anything survives, we emit the decal
10750         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]);
10751         if (numpoints < 3)
10752                 return;
10753         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]);
10754         if (numpoints < 3)
10755                 return;
10756         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]);
10757         if (numpoints < 3)
10758                 return;
10759         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]);
10760         if (numpoints < 3)
10761                 return;
10762         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]);
10763         if (numpoints < 3)
10764                 return;
10765         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]);
10766         if (numpoints < 3)
10767                 return;
10768         // some part of the triangle survived, so we have to accept it...
10769         if (dynamic)
10770         {
10771                 // dynamic always uses the original triangle
10772                 numpoints = 3;
10773                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10774                 {
10775                         index = 3*e[cornerindex];
10776                         VectorCopy(vertex3f + index, v[cornerindex]);
10777                 }
10778         }
10779         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10780         {
10781                 // convert vertex positions to texcoords
10782                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10783                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10784                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10785                 // calculate distance fade from the projection origin
10786                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10787                 f = bound(0.0f, f, 1.0f);
10788                 c[cornerindex][0] = r * f;
10789                 c[cornerindex][1] = g * f;
10790                 c[cornerindex][2] = b * f;
10791                 c[cornerindex][3] = 1.0f;
10792                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10793         }
10794         if (dynamic)
10795                 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);
10796         else
10797                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10798                         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);
10799 }
10800 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)
10801 {
10802         matrix4x4_t projection;
10803         decalsystem_t *decalsystem;
10804         qboolean dynamic;
10805         dp_model_t *model;
10806         const msurface_t *surface;
10807         const msurface_t *surfaces;
10808         const int *surfacelist;
10809         const texture_t *texture;
10810         int numtriangles;
10811         int numsurfacelist;
10812         int surfacelistindex;
10813         int surfaceindex;
10814         int triangleindex;
10815         float localorigin[3];
10816         float localnormal[3];
10817         float localmins[3];
10818         float localmaxs[3];
10819         float localsize;
10820         //float normal[3];
10821         float planes[6][4];
10822         float angles[3];
10823         bih_t *bih;
10824         int bih_triangles_count;
10825         int bih_triangles[256];
10826         int bih_surfaces[256];
10827
10828         decalsystem = &ent->decalsystem;
10829         model = ent->model;
10830         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10831         {
10832                 R_DecalSystem_Reset(&ent->decalsystem);
10833                 return;
10834         }
10835
10836         if (!model->brush.data_leafs && !cl_decals_models.integer)
10837         {
10838                 if (decalsystem->model)
10839                         R_DecalSystem_Reset(decalsystem);
10840                 return;
10841         }
10842
10843         if (decalsystem->model != model)
10844                 R_DecalSystem_Reset(decalsystem);
10845         decalsystem->model = model;
10846
10847         RSurf_ActiveModelEntity(ent, true, false, false);
10848
10849         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10850         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10851         VectorNormalize(localnormal);
10852         localsize = worldsize*rsurface.inversematrixscale;
10853         localmins[0] = localorigin[0] - localsize;
10854         localmins[1] = localorigin[1] - localsize;
10855         localmins[2] = localorigin[2] - localsize;
10856         localmaxs[0] = localorigin[0] + localsize;
10857         localmaxs[1] = localorigin[1] + localsize;
10858         localmaxs[2] = localorigin[2] + localsize;
10859
10860         //VectorCopy(localnormal, planes[4]);
10861         //VectorVectors(planes[4], planes[2], planes[0]);
10862         AnglesFromVectors(angles, localnormal, NULL, false);
10863         AngleVectors(angles, planes[0], planes[2], planes[4]);
10864         VectorNegate(planes[0], planes[1]);
10865         VectorNegate(planes[2], planes[3]);
10866         VectorNegate(planes[4], planes[5]);
10867         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10868         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10869         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10870         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10871         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10872         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10873
10874 #if 1
10875 // works
10876 {
10877         matrix4x4_t forwardprojection;
10878         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10879         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10880 }
10881 #else
10882 // broken
10883 {
10884         float projectionvector[4][3];
10885         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10886         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10887         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10888         projectionvector[0][0] = planes[0][0] * ilocalsize;
10889         projectionvector[0][1] = planes[1][0] * ilocalsize;
10890         projectionvector[0][2] = planes[2][0] * ilocalsize;
10891         projectionvector[1][0] = planes[0][1] * ilocalsize;
10892         projectionvector[1][1] = planes[1][1] * ilocalsize;
10893         projectionvector[1][2] = planes[2][1] * ilocalsize;
10894         projectionvector[2][0] = planes[0][2] * ilocalsize;
10895         projectionvector[2][1] = planes[1][2] * ilocalsize;
10896         projectionvector[2][2] = planes[2][2] * ilocalsize;
10897         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10898         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10899         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10900         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10901 }
10902 #endif
10903
10904         dynamic = model->surfmesh.isanimated;
10905         numsurfacelist = model->nummodelsurfaces;
10906         surfacelist = model->sortedmodelsurfaces;
10907         surfaces = model->data_surfaces;
10908
10909         bih = NULL;
10910         bih_triangles_count = -1;
10911         if(!dynamic)
10912         {
10913                 if(model->render_bih.numleafs)
10914                         bih = &model->render_bih;
10915                 else if(model->collision_bih.numleafs)
10916                         bih = &model->collision_bih;
10917         }
10918         if(bih)
10919                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10920         if(bih_triangles_count == 0)
10921                 return;
10922         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10923                 return;
10924         if(bih_triangles_count > 0)
10925         {
10926                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10927                 {
10928                         surfaceindex = bih_surfaces[triangleindex];
10929                         surface = surfaces + surfaceindex;
10930                         texture = surface->texture;
10931                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10932                                 continue;
10933                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10934                                 continue;
10935                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10936                 }
10937         }
10938         else
10939         {
10940                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10941                 {
10942                         surfaceindex = surfacelist[surfacelistindex];
10943                         surface = surfaces + surfaceindex;
10944                         // check cull box first because it rejects more than any other check
10945                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10946                                 continue;
10947                         // skip transparent surfaces
10948                         texture = surface->texture;
10949                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10950                                 continue;
10951                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10952                                 continue;
10953                         numtriangles = surface->num_triangles;
10954                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10955                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10956                 }
10957         }
10958 }
10959
10960 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10961 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)
10962 {
10963         int renderentityindex;
10964         float worldmins[3];
10965         float worldmaxs[3];
10966         entity_render_t *ent;
10967
10968         if (!cl_decals_newsystem.integer)
10969                 return;
10970
10971         worldmins[0] = worldorigin[0] - worldsize;
10972         worldmins[1] = worldorigin[1] - worldsize;
10973         worldmins[2] = worldorigin[2] - worldsize;
10974         worldmaxs[0] = worldorigin[0] + worldsize;
10975         worldmaxs[1] = worldorigin[1] + worldsize;
10976         worldmaxs[2] = worldorigin[2] + worldsize;
10977
10978         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10979
10980         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10981         {
10982                 ent = r_refdef.scene.entities[renderentityindex];
10983                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10984                         continue;
10985
10986                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10987         }
10988 }
10989
10990 typedef struct r_decalsystem_splatqueue_s
10991 {
10992         vec3_t worldorigin;
10993         vec3_t worldnormal;
10994         float color[4];
10995         float tcrange[4];
10996         float worldsize;
10997         int decalsequence;
10998 }
10999 r_decalsystem_splatqueue_t;
11000
11001 int r_decalsystem_numqueued = 0;
11002 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11003
11004 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)
11005 {
11006         r_decalsystem_splatqueue_t *queue;
11007
11008         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11009                 return;
11010
11011         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11012         VectorCopy(worldorigin, queue->worldorigin);
11013         VectorCopy(worldnormal, queue->worldnormal);
11014         Vector4Set(queue->color, r, g, b, a);
11015         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11016         queue->worldsize = worldsize;
11017         queue->decalsequence = cl.decalsequence++;
11018 }
11019
11020 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11021 {
11022         int i;
11023         r_decalsystem_splatqueue_t *queue;
11024
11025         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11026                 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);
11027         r_decalsystem_numqueued = 0;
11028 }
11029
11030 extern cvar_t cl_decals_max;
11031 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11032 {
11033         int i;
11034         decalsystem_t *decalsystem = &ent->decalsystem;
11035         int numdecals;
11036         int killsequence;
11037         tridecal_t *decal;
11038         float frametime;
11039         float lifetime;
11040
11041         if (!decalsystem->numdecals)
11042                 return;
11043
11044         if (r_showsurfaces.integer)
11045                 return;
11046
11047         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11048         {
11049                 R_DecalSystem_Reset(decalsystem);
11050                 return;
11051         }
11052
11053         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11054         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11055
11056         if (decalsystem->lastupdatetime)
11057                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11058         else
11059                 frametime = 0;
11060         decalsystem->lastupdatetime = r_refdef.scene.time;
11061         decal = decalsystem->decals;
11062         numdecals = decalsystem->numdecals;
11063
11064         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11065         {
11066                 if (decal->color4f[0][3])
11067                 {
11068                         decal->lived += frametime;
11069                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11070                         {
11071                                 memset(decal, 0, sizeof(*decal));
11072                                 if (decalsystem->freedecal > i)
11073                                         decalsystem->freedecal = i;
11074                         }
11075                 }
11076         }
11077         decal = decalsystem->decals;
11078         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11079                 numdecals--;
11080
11081         // collapse the array by shuffling the tail decals into the gaps
11082         for (;;)
11083         {
11084                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11085                         decalsystem->freedecal++;
11086                 if (decalsystem->freedecal == numdecals)
11087                         break;
11088                 decal[decalsystem->freedecal] = decal[--numdecals];
11089         }
11090
11091         decalsystem->numdecals = numdecals;
11092
11093         if (numdecals <= 0)
11094         {
11095                 // if there are no decals left, reset decalsystem
11096                 R_DecalSystem_Reset(decalsystem);
11097         }
11098 }
11099
11100 extern skinframe_t *decalskinframe;
11101 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11102 {
11103         int i;
11104         decalsystem_t *decalsystem = &ent->decalsystem;
11105         int numdecals;
11106         tridecal_t *decal;
11107         float faderate;
11108         float alpha;
11109         float *v3f;
11110         float *c4f;
11111         float *t2f;
11112         const int *e;
11113         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11114         int numtris = 0;
11115
11116         numdecals = decalsystem->numdecals;
11117         if (!numdecals)
11118                 return;
11119
11120         if (r_showsurfaces.integer)
11121                 return;
11122
11123         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11124         {
11125                 R_DecalSystem_Reset(decalsystem);
11126                 return;
11127         }
11128
11129         // if the model is static it doesn't matter what value we give for
11130         // wantnormals and wanttangents, so this logic uses only rules applicable
11131         // to a model, knowing that they are meaningless otherwise
11132         if (ent == r_refdef.scene.worldentity)
11133                 RSurf_ActiveWorldEntity();
11134         else
11135                 RSurf_ActiveModelEntity(ent, false, false, false);
11136
11137         decalsystem->lastupdatetime = r_refdef.scene.time;
11138         decal = decalsystem->decals;
11139
11140         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11141
11142         // update vertex positions for animated models
11143         v3f = decalsystem->vertex3f;
11144         c4f = decalsystem->color4f;
11145         t2f = decalsystem->texcoord2f;
11146         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11147         {
11148                 if (!decal->color4f[0][3])
11149                         continue;
11150
11151                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11152                         continue;
11153
11154                 // skip backfaces
11155                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11156                         continue;
11157
11158                 // update color values for fading decals
11159                 if (decal->lived >= cl_decals_time.value)
11160                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11161                 else
11162                         alpha = 1.0f;
11163
11164                 c4f[ 0] = decal->color4f[0][0] * alpha;
11165                 c4f[ 1] = decal->color4f[0][1] * alpha;
11166                 c4f[ 2] = decal->color4f[0][2] * alpha;
11167                 c4f[ 3] = 1;
11168                 c4f[ 4] = decal->color4f[1][0] * alpha;
11169                 c4f[ 5] = decal->color4f[1][1] * alpha;
11170                 c4f[ 6] = decal->color4f[1][2] * alpha;
11171                 c4f[ 7] = 1;
11172                 c4f[ 8] = decal->color4f[2][0] * alpha;
11173                 c4f[ 9] = decal->color4f[2][1] * alpha;
11174                 c4f[10] = decal->color4f[2][2] * alpha;
11175                 c4f[11] = 1;
11176
11177                 t2f[0] = decal->texcoord2f[0][0];
11178                 t2f[1] = decal->texcoord2f[0][1];
11179                 t2f[2] = decal->texcoord2f[1][0];
11180                 t2f[3] = decal->texcoord2f[1][1];
11181                 t2f[4] = decal->texcoord2f[2][0];
11182                 t2f[5] = decal->texcoord2f[2][1];
11183
11184                 // update vertex positions for animated models
11185                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11186                 {
11187                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11188                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11189                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11190                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11191                 }
11192                 else
11193                 {
11194                         VectorCopy(decal->vertex3f[0], v3f);
11195                         VectorCopy(decal->vertex3f[1], v3f + 3);
11196                         VectorCopy(decal->vertex3f[2], v3f + 6);
11197                 }
11198
11199                 if (r_refdef.fogenabled)
11200                 {
11201                         alpha = RSurf_FogVertex(v3f);
11202                         VectorScale(c4f, alpha, c4f);
11203                         alpha = RSurf_FogVertex(v3f + 3);
11204                         VectorScale(c4f + 4, alpha, c4f + 4);
11205                         alpha = RSurf_FogVertex(v3f + 6);
11206                         VectorScale(c4f + 8, alpha, c4f + 8);
11207                 }
11208
11209                 v3f += 9;
11210                 c4f += 12;
11211                 t2f += 6;
11212                 numtris++;
11213         }
11214
11215         if (numtris > 0)
11216         {
11217                 r_refdef.stats.drawndecals += numtris;
11218
11219                 // now render the decals all at once
11220                 // (this assumes they all use one particle font texture!)
11221                 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);
11222 //              R_Mesh_ResetTextureState();
11223                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11224                 GL_DepthMask(false);
11225                 GL_DepthRange(0, 1);
11226                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11227                 GL_DepthTest(true);
11228                 GL_CullFace(GL_NONE);
11229                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11230                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11231                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11232         }
11233 }
11234
11235 static void R_DrawModelDecals(void)
11236 {
11237         int i, numdecals;
11238
11239         // fade faster when there are too many decals
11240         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11241         for (i = 0;i < r_refdef.scene.numentities;i++)
11242                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11243
11244         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11245         for (i = 0;i < r_refdef.scene.numentities;i++)
11246                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11247                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11248
11249         R_DecalSystem_ApplySplatEntitiesQueue();
11250
11251         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11252         for (i = 0;i < r_refdef.scene.numentities;i++)
11253                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11254
11255         r_refdef.stats.totaldecals += numdecals;
11256
11257         if (r_showsurfaces.integer)
11258                 return;
11259
11260         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11261
11262         for (i = 0;i < r_refdef.scene.numentities;i++)
11263         {
11264                 if (!r_refdef.viewcache.entityvisible[i])
11265                         continue;
11266                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11267                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11268         }
11269 }
11270
11271 extern cvar_t mod_collision_bih;
11272 void R_DrawDebugModel(void)
11273 {
11274         entity_render_t *ent = rsurface.entity;
11275         int i, j, k, l, flagsmask;
11276         const msurface_t *surface;
11277         dp_model_t *model = ent->model;
11278         vec3_t v;
11279
11280         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11281                 return;
11282
11283         if (r_showoverdraw.value > 0)
11284         {
11285                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11286                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11287                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11288                 GL_DepthTest(false);
11289                 GL_DepthMask(false);
11290                 GL_DepthRange(0, 1);
11291                 GL_BlendFunc(GL_ONE, GL_ONE);
11292                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11293                 {
11294                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11295                                 continue;
11296                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11297                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11298                         {
11299                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11300                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11301                                 if (!rsurface.texture->currentlayers->depthmask)
11302                                         GL_Color(c, 0, 0, 1.0f);
11303                                 else if (ent == r_refdef.scene.worldentity)
11304                                         GL_Color(c, c, c, 1.0f);
11305                                 else
11306                                         GL_Color(0, c, 0, 1.0f);
11307                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11308                                 RSurf_DrawBatch();
11309                         }
11310                 }
11311                 rsurface.texture = NULL;
11312         }
11313
11314         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11315
11316 //      R_Mesh_ResetTextureState();
11317         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11318         GL_DepthRange(0, 1);
11319         GL_DepthTest(!r_showdisabledepthtest.integer);
11320         GL_DepthMask(false);
11321         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11322
11323         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11324         {
11325                 int triangleindex;
11326                 int bihleafindex;
11327                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11328                 const q3mbrush_t *brush;
11329                 const bih_t *bih = &model->collision_bih;
11330                 const bih_leaf_t *bihleaf;
11331                 float vertex3f[3][3];
11332                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11333                 cullbox = false;
11334                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11335                 {
11336                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11337                                 continue;
11338                         switch (bihleaf->type)
11339                         {
11340                         case BIH_BRUSH:
11341                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11342                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11343                                 {
11344                                         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);
11345                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11346                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11347                                 }
11348                                 break;
11349                         case BIH_COLLISIONTRIANGLE:
11350                                 triangleindex = bihleaf->itemindex;
11351                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11352                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11353                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11354                                 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);
11355                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11356                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11357                                 break;
11358                         case BIH_RENDERTRIANGLE:
11359                                 triangleindex = bihleaf->itemindex;
11360                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11361                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11362                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11363                                 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);
11364                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11365                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11366                                 break;
11367                         }
11368                 }
11369         }
11370
11371         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11372
11373 #ifndef USE_GLES2
11374         if (r_showtris.integer && qglPolygonMode)
11375         {
11376                 if (r_showdisabledepthtest.integer)
11377                 {
11378                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11379                         GL_DepthMask(false);
11380                 }
11381                 else
11382                 {
11383                         GL_BlendFunc(GL_ONE, GL_ZERO);
11384                         GL_DepthMask(true);
11385                 }
11386                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11387                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11388                 {
11389                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11390                                 continue;
11391                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11392                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11393                         {
11394                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11395                                 if (!rsurface.texture->currentlayers->depthmask)
11396                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11397                                 else if (ent == r_refdef.scene.worldentity)
11398                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11399                                 else
11400                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11401                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11402                                 RSurf_DrawBatch();
11403                         }
11404                 }
11405                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11406                 rsurface.texture = NULL;
11407         }
11408
11409         if (r_shownormals.value != 0 && qglBegin)
11410         {
11411                 if (r_showdisabledepthtest.integer)
11412                 {
11413                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11414                         GL_DepthMask(false);
11415                 }
11416                 else
11417                 {
11418                         GL_BlendFunc(GL_ONE, GL_ZERO);
11419                         GL_DepthMask(true);
11420                 }
11421                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11422                 {
11423                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11424                                 continue;
11425                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11426                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11427                         {
11428                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11429                                 qglBegin(GL_LINES);
11430                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11431                                 {
11432                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11433                                         {
11434                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11435                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11436                                                 qglVertex3f(v[0], v[1], v[2]);
11437                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11438                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11439                                                 qglVertex3f(v[0], v[1], v[2]);
11440                                         }
11441                                 }
11442                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11443                                 {
11444                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11445                                         {
11446                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11447                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11448                                                 qglVertex3f(v[0], v[1], v[2]);
11449                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11450                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11451                                                 qglVertex3f(v[0], v[1], v[2]);
11452                                         }
11453                                 }
11454                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11455                                 {
11456                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11457                                         {
11458                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11459                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11460                                                 qglVertex3f(v[0], v[1], v[2]);
11461                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11462                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11463                                                 qglVertex3f(v[0], v[1], v[2]);
11464                                         }
11465                                 }
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                                 qglEnd();
11479                                 CHECKGLERROR
11480                         }
11481                 }
11482                 rsurface.texture = NULL;
11483         }
11484 #endif
11485 }
11486
11487 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11488 int r_maxsurfacelist = 0;
11489 const msurface_t **r_surfacelist = NULL;
11490 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11491 {
11492         int i, j, endj, flagsmask;
11493         dp_model_t *model = r_refdef.scene.worldmodel;
11494         msurface_t *surfaces;
11495         unsigned char *update;
11496         int numsurfacelist = 0;
11497         if (model == NULL)
11498                 return;
11499
11500         if (r_maxsurfacelist < model->num_surfaces)
11501         {
11502                 r_maxsurfacelist = model->num_surfaces;
11503                 if (r_surfacelist)
11504                         Mem_Free((msurface_t**)r_surfacelist);
11505                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11506         }
11507
11508         RSurf_ActiveWorldEntity();
11509
11510         surfaces = model->data_surfaces;
11511         update = model->brushq1.lightmapupdateflags;
11512
11513         // update light styles on this submodel
11514         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11515         {
11516                 model_brush_lightstyleinfo_t *style;
11517                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11518                 {
11519                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11520                         {
11521                                 int *list = style->surfacelist;
11522                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11523                                 for (j = 0;j < style->numsurfaces;j++)
11524                                         update[list[j]] = true;
11525                         }
11526                 }
11527         }
11528
11529         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11530
11531         if (debug)
11532         {
11533                 R_DrawDebugModel();
11534                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11535                 return;
11536         }
11537
11538         rsurface.lightmaptexture = NULL;
11539         rsurface.deluxemaptexture = NULL;
11540         rsurface.uselightmaptexture = false;
11541         rsurface.texture = NULL;
11542         rsurface.rtlight = NULL;
11543         numsurfacelist = 0;
11544         // add visible surfaces to draw list
11545         for (i = 0;i < model->nummodelsurfaces;i++)
11546         {
11547                 j = model->sortedmodelsurfaces[i];
11548                 if (r_refdef.viewcache.world_surfacevisible[j])
11549                         r_surfacelist[numsurfacelist++] = surfaces + j;
11550         }
11551         // update lightmaps if needed
11552         if (model->brushq1.firstrender)
11553         {
11554                 model->brushq1.firstrender = false;
11555                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11556                         if (update[j])
11557                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11558         }
11559         else if (update)
11560         {
11561                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11562                         if (r_refdef.viewcache.world_surfacevisible[j])
11563                                 if (update[j])
11564                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11565         }
11566         // don't do anything if there were no surfaces
11567         if (!numsurfacelist)
11568         {
11569                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11570                 return;
11571         }
11572         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11573
11574         // add to stats if desired
11575         if (r_speeds.integer && !skysurfaces && !depthonly)
11576         {
11577                 r_refdef.stats.world_surfaces += numsurfacelist;
11578                 for (j = 0;j < numsurfacelist;j++)
11579                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11580         }
11581
11582         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11583 }
11584
11585 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11586 {
11587         int i, j, endj, flagsmask;
11588         dp_model_t *model = ent->model;
11589         msurface_t *surfaces;
11590         unsigned char *update;
11591         int numsurfacelist = 0;
11592         if (model == NULL)
11593                 return;
11594
11595         if (r_maxsurfacelist < model->num_surfaces)
11596         {
11597                 r_maxsurfacelist = model->num_surfaces;
11598                 if (r_surfacelist)
11599                         Mem_Free((msurface_t **)r_surfacelist);
11600                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11601         }
11602
11603         // if the model is static it doesn't matter what value we give for
11604         // wantnormals and wanttangents, so this logic uses only rules applicable
11605         // to a model, knowing that they are meaningless otherwise
11606         if (ent == r_refdef.scene.worldentity)
11607                 RSurf_ActiveWorldEntity();
11608         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11609                 RSurf_ActiveModelEntity(ent, false, false, false);
11610         else if (prepass)
11611                 RSurf_ActiveModelEntity(ent, true, true, true);
11612         else if (depthonly)
11613         {
11614                 switch (vid.renderpath)
11615                 {
11616                 case RENDERPATH_GL20:
11617                 case RENDERPATH_D3D9:
11618                 case RENDERPATH_D3D10:
11619                 case RENDERPATH_D3D11:
11620                 case RENDERPATH_SOFT:
11621                 case RENDERPATH_GLES2:
11622                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11623                         break;
11624                 case RENDERPATH_GL11:
11625                 case RENDERPATH_GL13:
11626                 case RENDERPATH_GLES1:
11627                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11628                         break;
11629                 }
11630         }
11631         else
11632         {
11633                 switch (vid.renderpath)
11634                 {
11635                 case RENDERPATH_GL20:
11636                 case RENDERPATH_D3D9:
11637                 case RENDERPATH_D3D10:
11638                 case RENDERPATH_D3D11:
11639                 case RENDERPATH_SOFT:
11640                 case RENDERPATH_GLES2:
11641                         RSurf_ActiveModelEntity(ent, true, true, false);
11642                         break;
11643                 case RENDERPATH_GL11:
11644                 case RENDERPATH_GL13:
11645                 case RENDERPATH_GLES1:
11646                         RSurf_ActiveModelEntity(ent, true, false, false);
11647                         break;
11648                 }
11649         }
11650
11651         surfaces = model->data_surfaces;
11652         update = model->brushq1.lightmapupdateflags;
11653
11654         // update light styles
11655         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11656         {
11657                 model_brush_lightstyleinfo_t *style;
11658                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11659                 {
11660                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11661                         {
11662                                 int *list = style->surfacelist;
11663                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11664                                 for (j = 0;j < style->numsurfaces;j++)
11665                                         update[list[j]] = true;
11666                         }
11667                 }
11668         }
11669
11670         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11671
11672         if (debug)
11673         {
11674                 R_DrawDebugModel();
11675                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11676                 return;
11677         }
11678
11679         rsurface.lightmaptexture = NULL;
11680         rsurface.deluxemaptexture = NULL;
11681         rsurface.uselightmaptexture = false;
11682         rsurface.texture = NULL;
11683         rsurface.rtlight = NULL;
11684         numsurfacelist = 0;
11685         // add visible surfaces to draw list
11686         for (i = 0;i < model->nummodelsurfaces;i++)
11687                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11688         // don't do anything if there were no surfaces
11689         if (!numsurfacelist)
11690         {
11691                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11692                 return;
11693         }
11694         // update lightmaps if needed
11695         if (update)
11696         {
11697                 int updated = 0;
11698                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11699                 {
11700                         if (update[j])
11701                         {
11702                                 updated++;
11703                                 R_BuildLightMap(ent, surfaces + j);
11704                         }
11705                 }
11706         }
11707         if (update)
11708                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11709                         if (update[j])
11710                                 R_BuildLightMap(ent, surfaces + j);
11711         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11712
11713         // add to stats if desired
11714         if (r_speeds.integer && !skysurfaces && !depthonly)
11715         {
11716                 r_refdef.stats.entities_surfaces += numsurfacelist;
11717                 for (j = 0;j < numsurfacelist;j++)
11718                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11719         }
11720
11721         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11722 }
11723
11724 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11725 {
11726         static texture_t texture;
11727         static msurface_t surface;
11728         const msurface_t *surfacelist = &surface;
11729
11730         // fake enough texture and surface state to render this geometry
11731
11732         texture.update_lastrenderframe = -1; // regenerate this texture
11733         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11734         texture.currentskinframe = skinframe;
11735         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11736         texture.offsetmapping = OFFSETMAPPING_OFF;
11737         texture.offsetscale = 1;
11738         texture.specularscalemod = 1;
11739         texture.specularpowermod = 1;
11740
11741         surface.texture = &texture;
11742         surface.num_triangles = numtriangles;
11743         surface.num_firsttriangle = firsttriangle;
11744         surface.num_vertices = numvertices;
11745         surface.num_firstvertex = firstvertex;
11746
11747         // now render it
11748         rsurface.texture = R_GetCurrentTexture(surface.texture);
11749         rsurface.lightmaptexture = NULL;
11750         rsurface.deluxemaptexture = NULL;
11751         rsurface.uselightmaptexture = false;
11752         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11753 }
11754
11755 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)
11756 {
11757         static msurface_t surface;
11758         const msurface_t *surfacelist = &surface;
11759
11760         // fake enough texture and surface state to render this geometry
11761         surface.texture = texture;
11762         surface.num_triangles = numtriangles;
11763         surface.num_firsttriangle = firsttriangle;
11764         surface.num_vertices = numvertices;
11765         surface.num_firstvertex = firstvertex;
11766
11767         // now render it
11768         rsurface.texture = R_GetCurrentTexture(surface.texture);
11769         rsurface.lightmaptexture = NULL;
11770         rsurface.deluxemaptexture = NULL;
11771         rsurface.uselightmaptexture = false;
11772         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11773 }