]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Experimental r_glsl_offsetmapping_lod cvar which applies a distance-based correction...
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141
142 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
143 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
144
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148
149 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
150 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
154 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
155 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157
158 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
166 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
167 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176
177 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)"};
178 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
179 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"};
180 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
181 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
182 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
183 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"};
184
185 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
186 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
187 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
188 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
189
190 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
191 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
192 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
193 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
194 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
195 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
196 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
197
198 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
199 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
200 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
201 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)"};
202 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
203 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
204 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
207 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
208 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
209
210 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"};
211
212 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"};
213
214 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
215
216 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
217
218 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
219 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"};
220
221 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."};
222
223 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)"};
224
225 extern cvar_t v_glslgamma;
226 extern cvar_t v_glslgamma_2d;
227
228 extern qboolean v_flipped_state;
229
230 static struct r_bloomstate_s
231 {
232         qboolean enabled;
233         qboolean hdr;
234
235         int bloomwidth, bloomheight;
236
237         textype_t texturetype;
238         int viewfbo; // used to check if r_viewfbo cvar has changed
239
240         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
241         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
242         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
243
244         int screentexturewidth, screentextureheight;
245         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
246
247         int bloomtexturewidth, bloomtextureheight;
248         rtexture_t *texture_bloom;
249
250         // arrays for rendering the screen passes
251         float screentexcoord2f[8];
252         float bloomtexcoord2f[8];
253         float offsettexcoord2f[8];
254
255         r_viewport_t viewport;
256 }
257 r_bloomstate;
258
259 r_waterstate_t r_waterstate;
260
261 /// shadow volume bsp struct with automatically growing nodes buffer
262 svbsp_t r_svbsp;
263
264 rtexture_t *r_texture_blanknormalmap;
265 rtexture_t *r_texture_white;
266 rtexture_t *r_texture_grey128;
267 rtexture_t *r_texture_black;
268 rtexture_t *r_texture_notexture;
269 rtexture_t *r_texture_whitecube;
270 rtexture_t *r_texture_normalizationcube;
271 rtexture_t *r_texture_fogattenuation;
272 rtexture_t *r_texture_fogheighttexture;
273 rtexture_t *r_texture_gammaramps;
274 unsigned int r_texture_gammaramps_serial;
275 //rtexture_t *r_texture_fogintensity;
276 rtexture_t *r_texture_reflectcube;
277
278 // TODO: hash lookups?
279 typedef struct cubemapinfo_s
280 {
281         char basename[64];
282         rtexture_t *texture;
283 }
284 cubemapinfo_t;
285
286 int r_texture_numcubemaps;
287 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
288
289 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
290 unsigned int r_numqueries;
291 unsigned int r_maxqueries;
292
293 typedef struct r_qwskincache_s
294 {
295         char name[MAX_QPATH];
296         skinframe_t *skinframe;
297 }
298 r_qwskincache_t;
299
300 static r_qwskincache_t *r_qwskincache;
301 static int r_qwskincache_size;
302
303 /// vertex coordinates for a quad that covers the screen exactly
304 extern const float r_screenvertex3f[12];
305 extern const float r_d3dscreenvertex3f[12];
306 const float r_screenvertex3f[12] =
307 {
308         0, 0, 0,
309         1, 0, 0,
310         1, 1, 0,
311         0, 1, 0
312 };
313 const float r_d3dscreenvertex3f[12] =
314 {
315         0, 1, 0,
316         1, 1, 0,
317         1, 0, 0,
318         0, 0, 0
319 };
320
321 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
322 {
323         int i;
324         for (i = 0;i < verts;i++)
325         {
326                 out[0] = in[0] * r;
327                 out[1] = in[1] * g;
328                 out[2] = in[2] * b;
329                 out[3] = in[3];
330                 in += 4;
331                 out += 4;
332         }
333 }
334
335 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
336 {
337         int i;
338         for (i = 0;i < verts;i++)
339         {
340                 out[0] = r;
341                 out[1] = g;
342                 out[2] = b;
343                 out[3] = a;
344                 out += 4;
345         }
346 }
347
348 // FIXME: move this to client?
349 void FOG_clear(void)
350 {
351         if (gamemode == GAME_NEHAHRA)
352         {
353                 Cvar_Set("gl_fogenable", "0");
354                 Cvar_Set("gl_fogdensity", "0.2");
355                 Cvar_Set("gl_fogred", "0.3");
356                 Cvar_Set("gl_foggreen", "0.3");
357                 Cvar_Set("gl_fogblue", "0.3");
358         }
359         r_refdef.fog_density = 0;
360         r_refdef.fog_red = 0;
361         r_refdef.fog_green = 0;
362         r_refdef.fog_blue = 0;
363         r_refdef.fog_alpha = 1;
364         r_refdef.fog_start = 0;
365         r_refdef.fog_end = 16384;
366         r_refdef.fog_height = 1<<30;
367         r_refdef.fog_fadedepth = 128;
368         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
369 }
370
371 static void R_BuildBlankTextures(void)
372 {
373         unsigned char data[4];
374         data[2] = 128; // normal X
375         data[1] = 128; // normal Y
376         data[0] = 255; // normal Z
377         data[3] = 128; // height
378         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379         data[0] = 255;
380         data[1] = 255;
381         data[2] = 255;
382         data[3] = 255;
383         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
384         data[0] = 128;
385         data[1] = 128;
386         data[2] = 128;
387         data[3] = 255;
388         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
389         data[0] = 0;
390         data[1] = 0;
391         data[2] = 0;
392         data[3] = 255;
393         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
394 }
395
396 static void R_BuildNoTexture(void)
397 {
398         int x, y;
399         unsigned char pix[16][16][4];
400         // this makes a light grey/dark grey checkerboard texture
401         for (y = 0;y < 16;y++)
402         {
403                 for (x = 0;x < 16;x++)
404                 {
405                         if ((y < 8) ^ (x < 8))
406                         {
407                                 pix[y][x][0] = 128;
408                                 pix[y][x][1] = 128;
409                                 pix[y][x][2] = 128;
410                                 pix[y][x][3] = 255;
411                         }
412                         else
413                         {
414                                 pix[y][x][0] = 64;
415                                 pix[y][x][1] = 64;
416                                 pix[y][x][2] = 64;
417                                 pix[y][x][3] = 255;
418                         }
419                 }
420         }
421         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
422 }
423
424 static void R_BuildWhiteCube(void)
425 {
426         unsigned char data[6*1*1*4];
427         memset(data, 255, sizeof(data));
428         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
429 }
430
431 static void R_BuildNormalizationCube(void)
432 {
433         int x, y, side;
434         vec3_t v;
435         vec_t s, t, intensity;
436 #define NORMSIZE 64
437         unsigned char *data;
438         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
439         for (side = 0;side < 6;side++)
440         {
441                 for (y = 0;y < NORMSIZE;y++)
442                 {
443                         for (x = 0;x < NORMSIZE;x++)
444                         {
445                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
446                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 switch(side)
448                                 {
449                                 default:
450                                 case 0:
451                                         v[0] = 1;
452                                         v[1] = -t;
453                                         v[2] = -s;
454                                         break;
455                                 case 1:
456                                         v[0] = -1;
457                                         v[1] = -t;
458                                         v[2] = s;
459                                         break;
460                                 case 2:
461                                         v[0] = s;
462                                         v[1] = 1;
463                                         v[2] = t;
464                                         break;
465                                 case 3:
466                                         v[0] = s;
467                                         v[1] = -1;
468                                         v[2] = -t;
469                                         break;
470                                 case 4:
471                                         v[0] = s;
472                                         v[1] = -t;
473                                         v[2] = 1;
474                                         break;
475                                 case 5:
476                                         v[0] = -s;
477                                         v[1] = -t;
478                                         v[2] = -1;
479                                         break;
480                                 }
481                                 intensity = 127.0f / sqrt(DotProduct(v, v));
482                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
483                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
484                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
485                                 data[((side*64+y)*64+x)*4+3] = 255;
486                         }
487                 }
488         }
489         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
490         Mem_Free(data);
491 }
492
493 static void R_BuildFogTexture(void)
494 {
495         int x, b;
496 #define FOGWIDTH 256
497         unsigned char data1[FOGWIDTH][4];
498         //unsigned char data2[FOGWIDTH][4];
499         double d, r, alpha;
500
501         r_refdef.fogmasktable_start = r_refdef.fog_start;
502         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
503         r_refdef.fogmasktable_range = r_refdef.fogrange;
504         r_refdef.fogmasktable_density = r_refdef.fog_density;
505
506         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
507         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
508         {
509                 d = (x * r - r_refdef.fogmasktable_start);
510                 if(developer_extra.integer)
511                         Con_DPrintf("%f ", d);
512                 d = max(0, d);
513                 if (r_fog_exp2.integer)
514                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
515                 else
516                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
517                 if(developer_extra.integer)
518                         Con_DPrintf(" : %f ", alpha);
519                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
520                 if(developer_extra.integer)
521                         Con_DPrintf(" = %f\n", alpha);
522                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
523         }
524
525         for (x = 0;x < FOGWIDTH;x++)
526         {
527                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
528                 data1[x][0] = b;
529                 data1[x][1] = b;
530                 data1[x][2] = b;
531                 data1[x][3] = 255;
532                 //data2[x][0] = 255 - b;
533                 //data2[x][1] = 255 - b;
534                 //data2[x][2] = 255 - b;
535                 //data2[x][3] = 255;
536         }
537         if (r_texture_fogattenuation)
538         {
539                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
540                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541         }
542         else
543         {
544                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
545                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
546         }
547 }
548
549 static void R_BuildFogHeightTexture(void)
550 {
551         unsigned char *inpixels;
552         int size;
553         int x;
554         int y;
555         int j;
556         float c[4];
557         float f;
558         inpixels = NULL;
559         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
560         if (r_refdef.fogheighttexturename[0])
561                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
562         if (!inpixels)
563         {
564                 r_refdef.fog_height_tablesize = 0;
565                 if (r_texture_fogheighttexture)
566                         R_FreeTexture(r_texture_fogheighttexture);
567                 r_texture_fogheighttexture = NULL;
568                 if (r_refdef.fog_height_table2d)
569                         Mem_Free(r_refdef.fog_height_table2d);
570                 r_refdef.fog_height_table2d = NULL;
571                 if (r_refdef.fog_height_table1d)
572                         Mem_Free(r_refdef.fog_height_table1d);
573                 r_refdef.fog_height_table1d = NULL;
574                 return;
575         }
576         size = image_width;
577         r_refdef.fog_height_tablesize = size;
578         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
579         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
580         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
581         Mem_Free(inpixels);
582         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
583         // average fog color table accounting for every fog layer between a point
584         // and the camera.  (Note: attenuation is handled separately!)
585         for (y = 0;y < size;y++)
586         {
587                 for (x = 0;x < size;x++)
588                 {
589                         Vector4Clear(c);
590                         f = 0;
591                         if (x < y)
592                         {
593                                 for (j = x;j <= y;j++)
594                                 {
595                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
596                                         f++;
597                                 }
598                         }
599                         else
600                         {
601                                 for (j = x;j >= y;j--)
602                                 {
603                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
604                                         f++;
605                                 }
606                         }
607                         f = 1.0f / f;
608                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
612                 }
613         }
614         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
615 }
616
617 //=======================================================================================================================================================
618
619 static const char *builtinshaderstring =
620 #include "shader_glsl.h"
621 ;
622
623 const char *builtinhlslshaderstring =
624 #include "shader_hlsl.h"
625 ;
626
627 char *glslshaderstring = NULL;
628 char *hlslshaderstring = NULL;
629
630 //=======================================================================================================================================================
631
632 typedef struct shaderpermutationinfo_s
633 {
634         const char *pretext;
635         const char *name;
636 }
637 shaderpermutationinfo_t;
638
639 typedef struct shadermodeinfo_s
640 {
641         const char *vertexfilename;
642         const char *geometryfilename;
643         const char *fragmentfilename;
644         const char *pretext;
645         const char *name;
646 }
647 shadermodeinfo_t;
648
649 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
650 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
651 {
652         {"#define USEDIFFUSE\n", " diffuse"},
653         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
654         {"#define USEVIEWTINT\n", " viewtint"},
655         {"#define USECOLORMAPPING\n", " colormapping"},
656         {"#define USESATURATION\n", " saturation"},
657         {"#define USEFOGINSIDE\n", " foginside"},
658         {"#define USEFOGOUTSIDE\n", " fogoutside"},
659         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
660         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
661         {"#define USEGAMMARAMPS\n", " gammaramps"},
662         {"#define USECUBEFILTER\n", " cubefilter"},
663         {"#define USEGLOW\n", " glow"},
664         {"#define USEBLOOM\n", " bloom"},
665         {"#define USESPECULAR\n", " specular"},
666         {"#define USEPOSTPROCESSING\n", " postprocessing"},
667         {"#define USEREFLECTION\n", " reflection"},
668         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
669         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
670         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
671         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
672         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
673         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
674         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
675         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
676         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
677         {"#define USEALPHAKILL\n", " alphakill"},
678         {"#define USEREFLECTCUBE\n", " reflectcube"},
679         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
680         {"#define USEBOUNCEGRID\n", " bouncegrid"},
681         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
682         {"#define USETRIPPY\n", " trippy"},
683 };
684
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
709 {
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
728 };
729
730 struct r_glsl_permutation_s;
731 typedef struct r_glsl_permutation_s
732 {
733         /// hash lookup data
734         struct r_glsl_permutation_s *hashnext;
735         unsigned int mode;
736         unsigned int permutation;
737
738         /// indicates if we have tried compiling this permutation already
739         qboolean compiled;
740         /// 0 if compilation failed
741         int program;
742         // texture units assigned to each detected uniform
743         int tex_Texture_First;
744         int tex_Texture_Second;
745         int tex_Texture_GammaRamps;
746         int tex_Texture_Normal;
747         int tex_Texture_Color;
748         int tex_Texture_Gloss;
749         int tex_Texture_Glow;
750         int tex_Texture_SecondaryNormal;
751         int tex_Texture_SecondaryColor;
752         int tex_Texture_SecondaryGloss;
753         int tex_Texture_SecondaryGlow;
754         int tex_Texture_Pants;
755         int tex_Texture_Shirt;
756         int tex_Texture_FogHeightTexture;
757         int tex_Texture_FogMask;
758         int tex_Texture_Lightmap;
759         int tex_Texture_Deluxemap;
760         int tex_Texture_Attenuation;
761         int tex_Texture_Cube;
762         int tex_Texture_Refraction;
763         int tex_Texture_Reflection;
764         int tex_Texture_ShadowMap2D;
765         int tex_Texture_CubeProjection;
766         int tex_Texture_ScreenDepth;
767         int tex_Texture_ScreenNormalMap;
768         int tex_Texture_ScreenDiffuse;
769         int tex_Texture_ScreenSpecular;
770         int tex_Texture_ReflectMask;
771         int tex_Texture_ReflectCube;
772         int tex_Texture_BounceGrid;
773         /// locations of detected uniforms in program object, or -1 if not found
774         int loc_Texture_First;
775         int loc_Texture_Second;
776         int loc_Texture_GammaRamps;
777         int loc_Texture_Normal;
778         int loc_Texture_Color;
779         int loc_Texture_Gloss;
780         int loc_Texture_Glow;
781         int loc_Texture_SecondaryNormal;
782         int loc_Texture_SecondaryColor;
783         int loc_Texture_SecondaryGloss;
784         int loc_Texture_SecondaryGlow;
785         int loc_Texture_Pants;
786         int loc_Texture_Shirt;
787         int loc_Texture_FogHeightTexture;
788         int loc_Texture_FogMask;
789         int loc_Texture_Lightmap;
790         int loc_Texture_Deluxemap;
791         int loc_Texture_Attenuation;
792         int loc_Texture_Cube;
793         int loc_Texture_Refraction;
794         int loc_Texture_Reflection;
795         int loc_Texture_ShadowMap2D;
796         int loc_Texture_CubeProjection;
797         int loc_Texture_ScreenDepth;
798         int loc_Texture_ScreenNormalMap;
799         int loc_Texture_ScreenDiffuse;
800         int loc_Texture_ScreenSpecular;
801         int loc_Texture_ReflectMask;
802         int loc_Texture_ReflectCube;
803         int loc_Texture_BounceGrid;
804         int loc_Alpha;
805         int loc_BloomBlur_Parameters;
806         int loc_ClientTime;
807         int loc_Color_Ambient;
808         int loc_Color_Diffuse;
809         int loc_Color_Specular;
810         int loc_Color_Glow;
811         int loc_Color_Pants;
812         int loc_Color_Shirt;
813         int loc_DeferredColor_Ambient;
814         int loc_DeferredColor_Diffuse;
815         int loc_DeferredColor_Specular;
816         int loc_DeferredMod_Diffuse;
817         int loc_DeferredMod_Specular;
818         int loc_DistortScaleRefractReflect;
819         int loc_EyePosition;
820         int loc_FogColor;
821         int loc_FogHeightFade;
822         int loc_FogPlane;
823         int loc_FogPlaneViewDist;
824         int loc_FogRangeRecip;
825         int loc_LightColor;
826         int loc_LightDir;
827         int loc_LightPosition;
828         int loc_OffsetMapping_ScaleSteps;
829         int loc_OffsetMapping_LodDistance;
830         int loc_PixelSize;
831         int loc_ReflectColor;
832         int loc_ReflectFactor;
833         int loc_ReflectOffset;
834         int loc_RefractColor;
835         int loc_Saturation;
836         int loc_ScreenCenterRefractReflect;
837         int loc_ScreenScaleRefractReflect;
838         int loc_ScreenToDepth;
839         int loc_ShadowMap_Parameters;
840         int loc_ShadowMap_TextureScale;
841         int loc_SpecularPower;
842         int loc_UserVec1;
843         int loc_UserVec2;
844         int loc_UserVec3;
845         int loc_UserVec4;
846         int loc_ViewTintColor;
847         int loc_ViewToLight;
848         int loc_ModelToLight;
849         int loc_TexMatrix;
850         int loc_BackgroundTexMatrix;
851         int loc_ModelViewProjectionMatrix;
852         int loc_ModelViewMatrix;
853         int loc_PixelToScreenTexCoord;
854         int loc_ModelToReflectCube;
855         int loc_ShadowMapMatrix;
856         int loc_BloomColorSubtract;
857         int loc_NormalmapScrollBlend;
858         int loc_BounceGridMatrix;
859         int loc_BounceGridIntensity;
860 }
861 r_glsl_permutation_t;
862
863 #define SHADERPERMUTATION_HASHSIZE 256
864
865
866 // non-degradable "lightweight" shader parameters to keep the permutations simpler
867 // these can NOT degrade! only use for simple stuff
868 enum
869 {
870         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
871         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
872         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
873         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
876         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
877         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
878 };
879 #define SHADERSTATICPARMS_COUNT 8
880
881 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
882 static int shaderstaticparms_count = 0;
883
884 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
885 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
886 qboolean R_CompileShader_CheckStaticParms(void)
887 {
888         static int r_compileshader_staticparms_save[1];
889         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
890         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
891
892         // detect all
893         if (r_glsl_saturation_redcompensate.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
895         if (r_glsl_vertextextureblend_usebothalphas.integer)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
897         if (r_shadow_glossexact.integer)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
899         if (r_glsl_postprocess.integer)
900         {
901                 if (r_glsl_postprocess_uservec1_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
903                 if (r_glsl_postprocess_uservec2_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
905                 if (r_glsl_postprocess_uservec3_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
907                 if (r_glsl_postprocess_uservec4_enable.integer)
908                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
909         }
910         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
912         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
913 }
914
915 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
916         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
917                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
918         else \
919                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
920 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
921 {
922         shaderstaticparms_count = 0;
923
924         // emit all
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
933 }
934
935 /// information about each possible shader permutation
936 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
937 /// currently selected permutation
938 r_glsl_permutation_t *r_glsl_permutation;
939 /// storage for permutations linked in the hash table
940 memexpandablearray_t r_glsl_permutationarray;
941
942 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
943 {
944         //unsigned int hashdepth = 0;
945         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
946         r_glsl_permutation_t *p;
947         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
948         {
949                 if (p->mode == mode && p->permutation == permutation)
950                 {
951                         //if (hashdepth > 10)
952                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
953                         return p;
954                 }
955                 //hashdepth++;
956         }
957         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
958         p->mode = mode;
959         p->permutation = permutation;
960         p->hashnext = r_glsl_permutationhash[mode][hashindex];
961         r_glsl_permutationhash[mode][hashindex] = p;
962         //if (hashdepth > 10)
963         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
964         return p;
965 }
966
967 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
968 {
969         char *shaderstring;
970         if (!filename || !filename[0])
971                 return NULL;
972         if (!strcmp(filename, "glsl/default.glsl"))
973         {
974                 if (!glslshaderstring)
975                 {
976                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
977                         if (glslshaderstring)
978                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
979                         else
980                                 glslshaderstring = (char *)builtinshaderstring;
981                 }
982                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
983                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
984                 return shaderstring;
985         }
986         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
987         if (shaderstring)
988         {
989                 if (printfromdisknotice)
990                         Con_DPrintf("from disk %s... ", filename);
991                 return shaderstring;
992         }
993         return shaderstring;
994 }
995
996 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
997 {
998         int i;
999         int sampler;
1000         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1001         char *vertexstring, *geometrystring, *fragmentstring;
1002         char permutationname[256];
1003         int vertstrings_count = 0;
1004         int geomstrings_count = 0;
1005         int fragstrings_count = 0;
1006         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1007         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009
1010         if (p->compiled)
1011                 return;
1012         p->compiled = true;
1013         p->program = 0;
1014
1015         permutationname[0] = 0;
1016         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1017         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1018         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1019
1020         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1021
1022         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1023         if(vid.support.gl20shaders130)
1024         {
1025                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1026                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1027                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1028                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1029                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1030                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1031         }
1032
1033         // the first pretext is which type of shader to compile as
1034         // (later these will all be bound together as a program object)
1035         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1036         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1037         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1038
1039         // the second pretext is the mode (for example a light source)
1040         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1041         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1042         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1043         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1044
1045         // now add all the permutation pretexts
1046         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1047         {
1048                 if (permutation & (1<<i))
1049                 {
1050                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1051                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1052                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1054                 }
1055                 else
1056                 {
1057                         // keep line numbers correct
1058                         vertstrings_list[vertstrings_count++] = "\n";
1059                         geomstrings_list[geomstrings_count++] = "\n";
1060                         fragstrings_list[fragstrings_count++] = "\n";
1061                 }
1062         }
1063
1064         // add static parms
1065         R_CompileShader_AddStaticParms(mode, permutation);
1066         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1067         vertstrings_count += shaderstaticparms_count;
1068         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069         geomstrings_count += shaderstaticparms_count;
1070         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         fragstrings_count += shaderstaticparms_count;
1072
1073         // now append the shader text itself
1074         vertstrings_list[vertstrings_count++] = vertexstring;
1075         geomstrings_list[geomstrings_count++] = geometrystring;
1076         fragstrings_list[fragstrings_count++] = fragmentstring;
1077
1078         // if any sources were NULL, clear the respective list
1079         if (!vertexstring)
1080                 vertstrings_count = 0;
1081         if (!geometrystring)
1082                 geomstrings_count = 0;
1083         if (!fragmentstring)
1084                 fragstrings_count = 0;
1085
1086         // compile the shader program
1087         if (vertstrings_count + geomstrings_count + fragstrings_count)
1088                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1089         if (p->program)
1090         {
1091                 CHECKGLERROR
1092                 qglUseProgram(p->program);CHECKGLERROR
1093                 // look up all the uniform variable names we care about, so we don't
1094                 // have to look them up every time we set them
1095
1096                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1097                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1098                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1099                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1100                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1101                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1102                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1103                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1104                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1105                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1106                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1107                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1108                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1109                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1110                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1111                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1112                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1113                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1114                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1115                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1116                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1117                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1118                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1119                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1120                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1121                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1122                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1123                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1124                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1125                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1126                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1127                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1128                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1129                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1130                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1131                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1132                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1133                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1134                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1135                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1136                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1137                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1138                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1139                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1140                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1141                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1142                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1143                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1144                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1145                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1146                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1147                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1148                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1149                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1150                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1151                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1152                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1153                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1154                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1155                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1156                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1157                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1158                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1159                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1160                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1161                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1162                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1163                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1164                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1165                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1166                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1167                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1168                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1169                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1170                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1171                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1172                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1173                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1174                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1175                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1176                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1177                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1178                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1179                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1180                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1181                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1182                 // initialize the samplers to refer to the texture units we use
1183                 p->tex_Texture_First = -1;
1184                 p->tex_Texture_Second = -1;
1185                 p->tex_Texture_GammaRamps = -1;
1186                 p->tex_Texture_Normal = -1;
1187                 p->tex_Texture_Color = -1;
1188                 p->tex_Texture_Gloss = -1;
1189                 p->tex_Texture_Glow = -1;
1190                 p->tex_Texture_SecondaryNormal = -1;
1191                 p->tex_Texture_SecondaryColor = -1;
1192                 p->tex_Texture_SecondaryGloss = -1;
1193                 p->tex_Texture_SecondaryGlow = -1;
1194                 p->tex_Texture_Pants = -1;
1195                 p->tex_Texture_Shirt = -1;
1196                 p->tex_Texture_FogHeightTexture = -1;
1197                 p->tex_Texture_FogMask = -1;
1198                 p->tex_Texture_Lightmap = -1;
1199                 p->tex_Texture_Deluxemap = -1;
1200                 p->tex_Texture_Attenuation = -1;
1201                 p->tex_Texture_Cube = -1;
1202                 p->tex_Texture_Refraction = -1;
1203                 p->tex_Texture_Reflection = -1;
1204                 p->tex_Texture_ShadowMap2D = -1;
1205                 p->tex_Texture_CubeProjection = -1;
1206                 p->tex_Texture_ScreenDepth = -1;
1207                 p->tex_Texture_ScreenNormalMap = -1;
1208                 p->tex_Texture_ScreenDiffuse = -1;
1209                 p->tex_Texture_ScreenSpecular = -1;
1210                 p->tex_Texture_ReflectMask = -1;
1211                 p->tex_Texture_ReflectCube = -1;
1212                 p->tex_Texture_BounceGrid = -1;
1213                 sampler = 0;
1214                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1215                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1216                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1217                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1218                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1219                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1220                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1221                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1225                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1226                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1227                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1228                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1229                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1230                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1231                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1232                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1233                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1234                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1235                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1236                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1237                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1241                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1243                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1244                 CHECKGLERROR
1245                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1246         }
1247         else
1248                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1249
1250         // free the strings
1251         if (vertexstring)
1252                 Mem_Free(vertexstring);
1253         if (geometrystring)
1254                 Mem_Free(geometrystring);
1255         if (fragmentstring)
1256                 Mem_Free(fragmentstring);
1257 }
1258
1259 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1260 {
1261         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1262         if (r_glsl_permutation != perm)
1263         {
1264                 r_glsl_permutation = perm;
1265                 if (!r_glsl_permutation->program)
1266                 {
1267                         if (!r_glsl_permutation->compiled)
1268                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                         if (!r_glsl_permutation->program)
1270                         {
1271                                 // remove features until we find a valid permutation
1272                                 int i;
1273                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1274                                 {
1275                                         // reduce i more quickly whenever it would not remove any bits
1276                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1277                                         if (!(permutation & j))
1278                                                 continue;
1279                                         permutation -= j;
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         if (!r_glsl_permutation->compiled)
1282                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1283                                         if (r_glsl_permutation->program)
1284                                                 break;
1285                                 }
1286                                 if (i >= SHADERPERMUTATION_COUNT)
1287                                 {
1288                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1289                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290                                         qglUseProgram(0);CHECKGLERROR
1291                                         return; // no bit left to clear, entire mode is broken
1292                                 }
1293                         }
1294                 }
1295                 CHECKGLERROR
1296                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1297         }
1298         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1299         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1300         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 }
1302
1303 #ifdef SUPPORTD3D
1304
1305 #ifdef SUPPORTD3D
1306 #include <d3d9.h>
1307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1308 extern D3DCAPS9 vid_d3d9caps;
1309 #endif
1310
1311 struct r_hlsl_permutation_s;
1312 typedef struct r_hlsl_permutation_s
1313 {
1314         /// hash lookup data
1315         struct r_hlsl_permutation_s *hashnext;
1316         unsigned int mode;
1317         unsigned int permutation;
1318
1319         /// indicates if we have tried compiling this permutation already
1320         qboolean compiled;
1321         /// NULL if compilation failed
1322         IDirect3DVertexShader9 *vertexshader;
1323         IDirect3DPixelShader9 *pixelshader;
1324 }
1325 r_hlsl_permutation_t;
1326
1327 typedef enum D3DVSREGISTER_e
1328 {
1329         D3DVSREGISTER_TexMatrix = 0, // float4x4
1330         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1331         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1332         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1333         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1334         D3DVSREGISTER_ModelToLight = 20, // float4x4
1335         D3DVSREGISTER_EyePosition = 24,
1336         D3DVSREGISTER_FogPlane = 25,
1337         D3DVSREGISTER_LightDir = 26,
1338         D3DVSREGISTER_LightPosition = 27,
1339 }
1340 D3DVSREGISTER_t;
1341
1342 typedef enum D3DPSREGISTER_e
1343 {
1344         D3DPSREGISTER_Alpha = 0,
1345         D3DPSREGISTER_BloomBlur_Parameters = 1,
1346         D3DPSREGISTER_ClientTime = 2,
1347         D3DPSREGISTER_Color_Ambient = 3,
1348         D3DPSREGISTER_Color_Diffuse = 4,
1349         D3DPSREGISTER_Color_Specular = 5,
1350         D3DPSREGISTER_Color_Glow = 6,
1351         D3DPSREGISTER_Color_Pants = 7,
1352         D3DPSREGISTER_Color_Shirt = 8,
1353         D3DPSREGISTER_DeferredColor_Ambient = 9,
1354         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1355         D3DPSREGISTER_DeferredColor_Specular = 11,
1356         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1357         D3DPSREGISTER_DeferredMod_Specular = 13,
1358         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1359         D3DPSREGISTER_EyePosition = 15, // unused
1360         D3DPSREGISTER_FogColor = 16,
1361         D3DPSREGISTER_FogHeightFade = 17,
1362         D3DPSREGISTER_FogPlane = 18,
1363         D3DPSREGISTER_FogPlaneViewDist = 19,
1364         D3DPSREGISTER_FogRangeRecip = 20,
1365         D3DPSREGISTER_LightColor = 21,
1366         D3DPSREGISTER_LightDir = 22, // unused
1367         D3DPSREGISTER_LightPosition = 23,
1368         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1369         D3DPSREGISTER_PixelSize = 25,
1370         D3DPSREGISTER_ReflectColor = 26,
1371         D3DPSREGISTER_ReflectFactor = 27,
1372         D3DPSREGISTER_ReflectOffset = 28,
1373         D3DPSREGISTER_RefractColor = 29,
1374         D3DPSREGISTER_Saturation = 30,
1375         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1376         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1377         D3DPSREGISTER_ScreenToDepth = 33,
1378         D3DPSREGISTER_ShadowMap_Parameters = 34,
1379         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1380         D3DPSREGISTER_SpecularPower = 36,
1381         D3DPSREGISTER_UserVec1 = 37,
1382         D3DPSREGISTER_UserVec2 = 38,
1383         D3DPSREGISTER_UserVec3 = 39,
1384         D3DPSREGISTER_UserVec4 = 40,
1385         D3DPSREGISTER_ViewTintColor = 41,
1386         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1387         D3DPSREGISTER_BloomColorSubtract = 43,
1388         D3DPSREGISTER_ViewToLight = 44, // float4x4
1389         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1390         D3DPSREGISTER_NormalmapScrollBlend = 52,
1391         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1392         // next at 54
1393 }
1394 D3DPSREGISTER_t;
1395
1396 /// information about each possible shader permutation
1397 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1398 /// currently selected permutation
1399 r_hlsl_permutation_t *r_hlsl_permutation;
1400 /// storage for permutations linked in the hash table
1401 memexpandablearray_t r_hlsl_permutationarray;
1402
1403 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1404 {
1405         //unsigned int hashdepth = 0;
1406         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1407         r_hlsl_permutation_t *p;
1408         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1409         {
1410                 if (p->mode == mode && p->permutation == permutation)
1411                 {
1412                         //if (hashdepth > 10)
1413                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1414                         return p;
1415                 }
1416                 //hashdepth++;
1417         }
1418         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1419         p->mode = mode;
1420         p->permutation = permutation;
1421         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1422         r_hlsl_permutationhash[mode][hashindex] = p;
1423         //if (hashdepth > 10)
1424         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1425         return p;
1426 }
1427
1428 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1429 {
1430         char *shaderstring;
1431         if (!filename || !filename[0])
1432                 return NULL;
1433         if (!strcmp(filename, "hlsl/default.hlsl"))
1434         {
1435                 if (!hlslshaderstring)
1436                 {
1437                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1438                         if (hlslshaderstring)
1439                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1440                         else
1441                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1442                 }
1443                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1444                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1445                 return shaderstring;
1446         }
1447         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1448         if (shaderstring)
1449         {
1450                 if (printfromdisknotice)
1451                         Con_DPrintf("from disk %s... ", filename);
1452                 return shaderstring;
1453         }
1454         return shaderstring;
1455 }
1456
1457 #include <d3dx9.h>
1458 //#include <d3dx9shader.h>
1459 //#include <d3dx9mesh.h>
1460
1461 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1462 {
1463         DWORD *vsbin = NULL;
1464         DWORD *psbin = NULL;
1465         fs_offset_t vsbinsize;
1466         fs_offset_t psbinsize;
1467 //      IDirect3DVertexShader9 *vs = NULL;
1468 //      IDirect3DPixelShader9 *ps = NULL;
1469         ID3DXBuffer *vslog = NULL;
1470         ID3DXBuffer *vsbuffer = NULL;
1471         ID3DXConstantTable *vsconstanttable = NULL;
1472         ID3DXBuffer *pslog = NULL;
1473         ID3DXBuffer *psbuffer = NULL;
1474         ID3DXConstantTable *psconstanttable = NULL;
1475         int vsresult = 0;
1476         int psresult = 0;
1477         char temp[MAX_INPUTLINE];
1478         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1479         qboolean debugshader = gl_paranoid.integer != 0;
1480         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1481         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1482         if (!debugshader)
1483         {
1484                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1485                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1486         }
1487         if ((!vsbin && vertstring) || (!psbin && fragstring))
1488         {
1489                 const char* dllnames_d3dx9 [] =
1490                 {
1491                         "d3dx9_43.dll",
1492                         "d3dx9_42.dll",
1493                         "d3dx9_41.dll",
1494                         "d3dx9_40.dll",
1495                         "d3dx9_39.dll",
1496                         "d3dx9_38.dll",
1497                         "d3dx9_37.dll",
1498                         "d3dx9_36.dll",
1499                         "d3dx9_35.dll",
1500                         "d3dx9_34.dll",
1501                         "d3dx9_33.dll",
1502                         "d3dx9_32.dll",
1503                         "d3dx9_31.dll",
1504                         "d3dx9_30.dll",
1505                         "d3dx9_29.dll",
1506                         "d3dx9_28.dll",
1507                         "d3dx9_27.dll",
1508                         "d3dx9_26.dll",
1509                         "d3dx9_25.dll",
1510                         "d3dx9_24.dll",
1511                         NULL
1512                 };
1513                 dllhandle_t d3dx9_dll = NULL;
1514                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1515                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1516                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1517                 dllfunction_t d3dx9_dllfuncs[] =
1518                 {
1519                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1520                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1521                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1522                         {NULL, NULL}
1523                 };
1524                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1525                 {
1526                         DWORD shaderflags = 0;
1527                         if (debugshader)
1528                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1529                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1530                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1531                         if (vertstring && vertstring[0])
1532                         {
1533                                 if (debugshader)
1534                                 {
1535 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1536 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1537                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1538                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1539                                 }
1540                                 else
1541                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542                                 if (vsbuffer)
1543                                 {
1544                                         vsbinsize = vsbuffer->GetBufferSize();
1545                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1546                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1547                                         vsbuffer->Release();
1548                                 }
1549                                 if (vslog)
1550                                 {
1551                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1552                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1553                                         vslog->Release();
1554                                 }
1555                         }
1556                         if (fragstring && fragstring[0])
1557                         {
1558                                 if (debugshader)
1559                                 {
1560 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1561 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1562                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1563                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1564                                 }
1565                                 else
1566                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 if (psbuffer)
1568                                 {
1569                                         psbinsize = psbuffer->GetBufferSize();
1570                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1571                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1572                                         psbuffer->Release();
1573                                 }
1574                                 if (pslog)
1575                                 {
1576                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1577                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1578                                         pslog->Release();
1579                                 }
1580                         }
1581                         Sys_UnloadLibrary(&d3dx9_dll);
1582                 }
1583                 else
1584                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1585         }
1586         if (vsbin && psbin)
1587         {
1588                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1589                 if (FAILED(vsresult))
1590                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1591                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1592                 if (FAILED(psresult))
1593                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1594         }
1595         // free the shader data
1596         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1597         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1598 }
1599
1600 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1601 {
1602         int i;
1603         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1604         int vertstring_length = 0;
1605         int geomstring_length = 0;
1606         int fragstring_length = 0;
1607         char *t;
1608         char *vertexstring, *geometrystring, *fragmentstring;
1609         char *vertstring, *geomstring, *fragstring;
1610         char permutationname[256];
1611         char cachename[256];
1612         int vertstrings_count = 0;
1613         int geomstrings_count = 0;
1614         int fragstrings_count = 0;
1615         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1616         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1618
1619         if (p->compiled)
1620                 return;
1621         p->compiled = true;
1622         p->vertexshader = NULL;
1623         p->pixelshader = NULL;
1624
1625         permutationname[0] = 0;
1626         cachename[0] = 0;
1627         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1628         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1629         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1630
1631         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1632         strlcat(cachename, "hlsl/", sizeof(cachename));
1633
1634         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1635         vertstrings_count = 0;
1636         geomstrings_count = 0;
1637         fragstrings_count = 0;
1638         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1639         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1640         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1641
1642         // the first pretext is which type of shader to compile as
1643         // (later these will all be bound together as a program object)
1644         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1645         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1646         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1647
1648         // the second pretext is the mode (for example a light source)
1649         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1650         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1651         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1652         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1653         strlcat(cachename, modeinfo->name, sizeof(cachename));
1654
1655         // now add all the permutation pretexts
1656         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1657         {
1658                 if (permutation & (1<<i))
1659                 {
1660                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1661                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1662                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1664                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1665                 }
1666                 else
1667                 {
1668                         // keep line numbers correct
1669                         vertstrings_list[vertstrings_count++] = "\n";
1670                         geomstrings_list[geomstrings_count++] = "\n";
1671                         fragstrings_list[fragstrings_count++] = "\n";
1672                 }
1673         }
1674
1675         // add static parms
1676         R_CompileShader_AddStaticParms(mode, permutation);
1677         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1678         vertstrings_count += shaderstaticparms_count;
1679         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680         geomstrings_count += shaderstaticparms_count;
1681         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         fragstrings_count += shaderstaticparms_count;
1683
1684         // replace spaces in the cachename with _ characters
1685         for (i = 0;cachename[i];i++)
1686                 if (cachename[i] == ' ')
1687                         cachename[i] = '_';
1688
1689         // now append the shader text itself
1690         vertstrings_list[vertstrings_count++] = vertexstring;
1691         geomstrings_list[geomstrings_count++] = geometrystring;
1692         fragstrings_list[fragstrings_count++] = fragmentstring;
1693
1694         // if any sources were NULL, clear the respective list
1695         if (!vertexstring)
1696                 vertstrings_count = 0;
1697         if (!geometrystring)
1698                 geomstrings_count = 0;
1699         if (!fragmentstring)
1700                 fragstrings_count = 0;
1701
1702         vertstring_length = 0;
1703         for (i = 0;i < vertstrings_count;i++)
1704                 vertstring_length += strlen(vertstrings_list[i]);
1705         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1706         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1707                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1708
1709         geomstring_length = 0;
1710         for (i = 0;i < geomstrings_count;i++)
1711                 geomstring_length += strlen(geomstrings_list[i]);
1712         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1713         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1714                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1715
1716         fragstring_length = 0;
1717         for (i = 0;i < fragstrings_count;i++)
1718                 fragstring_length += strlen(fragstrings_list[i]);
1719         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1720         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1721                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1722
1723         // try to load the cached shader, or generate one
1724         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1725
1726         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1727                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1728         else
1729                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1730
1731         // free the strings
1732         if (vertstring)
1733                 Mem_Free(vertstring);
1734         if (geomstring)
1735                 Mem_Free(geomstring);
1736         if (fragstring)
1737                 Mem_Free(fragstring);
1738         if (vertexstring)
1739                 Mem_Free(vertexstring);
1740         if (geometrystring)
1741                 Mem_Free(geometrystring);
1742         if (fragmentstring)
1743                 Mem_Free(fragmentstring);
1744 }
1745
1746 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1747 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1748 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);}
1749 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);}
1750 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);}
1751 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);}
1752
1753 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1754 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1755 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);}
1756 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);}
1757 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);}
1758 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);}
1759
1760 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1761 {
1762         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1763         if (r_hlsl_permutation != perm)
1764         {
1765                 r_hlsl_permutation = perm;
1766                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1767                 {
1768                         if (!r_hlsl_permutation->compiled)
1769                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1770                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1771                         {
1772                                 // remove features until we find a valid permutation
1773                                 int i;
1774                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1775                                 {
1776                                         // reduce i more quickly whenever it would not remove any bits
1777                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1778                                         if (!(permutation & j))
1779                                                 continue;
1780                                         permutation -= j;
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         if (!r_hlsl_permutation->compiled)
1783                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1784                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1785                                                 break;
1786                                 }
1787                                 if (i >= SHADERPERMUTATION_COUNT)
1788                                 {
1789                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1790                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1791                                         return; // no bit left to clear, entire mode is broken
1792                                 }
1793                         }
1794                 }
1795                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1796                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1797         }
1798         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1799         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1800         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1801 }
1802 #endif
1803
1804 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1805 {
1806         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1807         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1808         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1809         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1810 }
1811
1812 void R_GLSL_Restart_f(void)
1813 {
1814         unsigned int i, limit;
1815         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1816                 Mem_Free(glslshaderstring);
1817         glslshaderstring = NULL;
1818         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1819                 Mem_Free(hlslshaderstring);
1820         hlslshaderstring = NULL;
1821         switch(vid.renderpath)
1822         {
1823         case RENDERPATH_D3D9:
1824 #ifdef SUPPORTD3D
1825                 {
1826                         r_hlsl_permutation_t *p;
1827                         r_hlsl_permutation = NULL;
1828                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1829                         for (i = 0;i < limit;i++)
1830                         {
1831                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1832                                 {
1833                                         if (p->vertexshader)
1834                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1835                                         if (p->pixelshader)
1836                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1837                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1838                                 }
1839                         }
1840                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1841                 }
1842 #endif
1843                 break;
1844         case RENDERPATH_D3D10:
1845                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1846                 break;
1847         case RENDERPATH_D3D11:
1848                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_GL20:
1851         case RENDERPATH_GLES2:
1852                 {
1853                         r_glsl_permutation_t *p;
1854                         r_glsl_permutation = NULL;
1855                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1856                         for (i = 0;i < limit;i++)
1857                         {
1858                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1859                                 {
1860                                         GL_Backend_FreeProgram(p->program);
1861                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1862                                 }
1863                         }
1864                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1865                 }
1866                 break;
1867         case RENDERPATH_GL11:
1868         case RENDERPATH_GL13:
1869         case RENDERPATH_GLES1:
1870                 break;
1871         case RENDERPATH_SOFT:
1872                 break;
1873         }
1874 }
1875
1876 void R_GLSL_DumpShader_f(void)
1877 {
1878         int i;
1879         qfile_t *file;
1880
1881         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1882         if (file)
1883         {
1884                 FS_Print(file, "/* The engine may define the following macros:\n");
1885                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1886                 for (i = 0;i < SHADERMODE_COUNT;i++)
1887                         FS_Print(file, glslshadermodeinfo[i].pretext);
1888                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1889                         FS_Print(file, shaderpermutationinfo[i].pretext);
1890                 FS_Print(file, "*/\n");
1891                 FS_Print(file, builtinshaderstring);
1892                 FS_Close(file);
1893                 Con_Printf("glsl/default.glsl written\n");
1894         }
1895         else
1896                 Con_Printf("failed to write to glsl/default.glsl\n");
1897
1898         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1899         if (file)
1900         {
1901                 FS_Print(file, "/* The engine may define the following macros:\n");
1902                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1903                 for (i = 0;i < SHADERMODE_COUNT;i++)
1904                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1905                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1906                         FS_Print(file, shaderpermutationinfo[i].pretext);
1907                 FS_Print(file, "*/\n");
1908                 FS_Print(file, builtinhlslshaderstring);
1909                 FS_Close(file);
1910                 Con_Printf("hlsl/default.hlsl written\n");
1911         }
1912         else
1913                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1914 }
1915
1916 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1917 {
1918         unsigned int permutation = 0;
1919         if (r_trippy.integer && !notrippy)
1920                 permutation |= SHADERPERMUTATION_TRIPPY;
1921         permutation |= SHADERPERMUTATION_VIEWTINT;
1922         if (first)
1923                 permutation |= SHADERPERMUTATION_DIFFUSE;
1924         if (second)
1925                 permutation |= SHADERPERMUTATION_SPECULAR;
1926         if (texturemode == GL_MODULATE)
1927                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1928         else if (texturemode == GL_ADD)
1929                 permutation |= SHADERPERMUTATION_GLOW;
1930         else if (texturemode == GL_DECAL)
1931                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1932         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1933                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1934         if (!second)
1935                 texturemode = GL_MODULATE;
1936         if (vid.allowalphatocoverage)
1937                 GL_AlphaToCoverage(false);
1938         switch (vid.renderpath)
1939         {
1940         case RENDERPATH_D3D9:
1941 #ifdef SUPPORTD3D
1942                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1943                 R_Mesh_TexBind(GL20TU_FIRST , first );
1944                 R_Mesh_TexBind(GL20TU_SECOND, second);
1945                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1946                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1947 #endif
1948                 break;
1949         case RENDERPATH_D3D10:
1950                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951                 break;
1952         case RENDERPATH_D3D11:
1953                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1954                 break;
1955         case RENDERPATH_GL20:
1956         case RENDERPATH_GLES2:
1957                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1958                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1959                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1960                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1961                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1962                 break;
1963         case RENDERPATH_GL13:
1964         case RENDERPATH_GLES1:
1965                 R_Mesh_TexBind(0, first );
1966                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1967                 R_Mesh_TexBind(1, second);
1968                 if (second)
1969                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1970                 break;
1971         case RENDERPATH_GL11:
1972                 R_Mesh_TexBind(0, first );
1973                 break;
1974         case RENDERPATH_SOFT:
1975                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1976                 R_Mesh_TexBind(GL20TU_FIRST , first );
1977                 R_Mesh_TexBind(GL20TU_SECOND, second);
1978                 break;
1979         }
1980 }
1981
1982 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1983 {
1984         unsigned int permutation = 0;
1985         if (r_trippy.integer && !notrippy)
1986                 permutation |= SHADERPERMUTATION_TRIPPY;
1987         if (vid.allowalphatocoverage)
1988                 GL_AlphaToCoverage(false);
1989         switch (vid.renderpath)
1990         {
1991         case RENDERPATH_D3D9:
1992 #ifdef SUPPORTD3D
1993                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1994 #endif
1995                 break;
1996         case RENDERPATH_D3D10:
1997                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998                 break;
1999         case RENDERPATH_D3D11:
2000                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2001                 break;
2002         case RENDERPATH_GL20:
2003         case RENDERPATH_GLES2:
2004                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2005                 break;
2006         case RENDERPATH_GL13:
2007         case RENDERPATH_GLES1:
2008                 R_Mesh_TexBind(0, 0);
2009                 R_Mesh_TexBind(1, 0);
2010                 break;
2011         case RENDERPATH_GL11:
2012                 R_Mesh_TexBind(0, 0);
2013                 break;
2014         case RENDERPATH_SOFT:
2015                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016                 break;
2017         }
2018 }
2019
2020 void R_SetupShader_ShowDepth(qboolean notrippy)
2021 {
2022         int permutation = 0;
2023         if (r_trippy.integer && !notrippy)
2024                 permutation |= SHADERPERMUTATION_TRIPPY;
2025         if (vid.allowalphatocoverage)
2026                 GL_AlphaToCoverage(false);
2027         switch (vid.renderpath)
2028         {
2029         case RENDERPATH_D3D9:
2030 #ifdef SUPPORTHLSL
2031                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2032 #endif
2033                 break;
2034         case RENDERPATH_D3D10:
2035                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2036                 break;
2037         case RENDERPATH_D3D11:
2038                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2039                 break;
2040         case RENDERPATH_GL20:
2041         case RENDERPATH_GLES2:
2042                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2043                 break;
2044         case RENDERPATH_GL13:
2045         case RENDERPATH_GLES1:
2046                 break;
2047         case RENDERPATH_GL11:
2048                 break;
2049         case RENDERPATH_SOFT:
2050                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2051                 break;
2052         }
2053 }
2054
2055 extern qboolean r_shadow_usingdeferredprepass;
2056 extern cvar_t r_shadow_deferred_8bitrange;
2057 extern rtexture_t *r_shadow_attenuationgradienttexture;
2058 extern rtexture_t *r_shadow_attenuation2dtexture;
2059 extern rtexture_t *r_shadow_attenuation3dtexture;
2060 extern qboolean r_shadow_usingshadowmap2d;
2061 extern qboolean r_shadow_usingshadowmaportho;
2062 extern float r_shadow_shadowmap_texturescale[2];
2063 extern float r_shadow_shadowmap_parameters[4];
2064 extern qboolean r_shadow_shadowmapvsdct;
2065 extern qboolean r_shadow_shadowmapsampler;
2066 extern int r_shadow_shadowmappcf;
2067 extern rtexture_t *r_shadow_shadowmap2dtexture;
2068 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2069 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2070 extern matrix4x4_t r_shadow_shadowmapmatrix;
2071 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2072 extern int r_shadow_prepass_width;
2073 extern int r_shadow_prepass_height;
2074 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2075 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2076 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2077 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2078 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2079
2080 #define BLENDFUNC_ALLOWS_COLORMOD      1
2081 #define BLENDFUNC_ALLOWS_FOG           2
2082 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2083 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2084 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2085 static int R_BlendFuncFlags(int src, int dst)
2086 {
2087         int r = 0;
2088
2089         // a blendfunc allows colormod if:
2090         // a) it can never keep the destination pixel invariant, or
2091         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2092         // this is to prevent unintended side effects from colormod
2093
2094         // a blendfunc allows fog if:
2095         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2096         // this is to prevent unintended side effects from fog
2097
2098         // these checks are the output of fogeval.pl
2099
2100         r |= BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2102         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2106         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2110         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2113         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2114         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2116         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2117         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2119         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2122
2123         return r;
2124 }
2125
2126 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)
2127 {
2128         // select a permutation of the lighting shader appropriate to this
2129         // combination of texture, entity, light source, and fogging, only use the
2130         // minimum features necessary to avoid wasting rendering time in the
2131         // fragment shader on features that are not being used
2132         unsigned int permutation = 0;
2133         unsigned int mode = 0;
2134         int blendfuncflags;
2135         static float dummy_colormod[3] = {1, 1, 1};
2136         float *colormod = rsurface.colormod;
2137         float m16f[16];
2138         matrix4x4_t tempmatrix;
2139         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2140         if (r_trippy.integer && !notrippy)
2141                 permutation |= SHADERPERMUTATION_TRIPPY;
2142         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2143                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2144         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2145                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2146         if (rsurfacepass == RSURFPASS_BACKGROUND)
2147         {
2148                 // distorted background
2149                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2150                 {
2151                         mode = SHADERMODE_WATER;
2152                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2153                         {
2154                                 // this is the right thing to do for wateralpha
2155                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2156                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2157                         }
2158                         else
2159                         {
2160                                 // this is the right thing to do for entity alpha
2161                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163                         }
2164                 }
2165                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2166                 {
2167                         mode = SHADERMODE_REFRACTION;
2168                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2169                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                 }
2171                 else
2172                 {
2173                         mode = SHADERMODE_GENERIC;
2174                         permutation |= SHADERPERMUTATION_DIFFUSE;
2175                         GL_BlendFunc(GL_ONE, GL_ZERO);
2176                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2177                 }
2178                 if (vid.allowalphatocoverage)
2179                         GL_AlphaToCoverage(false);
2180         }
2181         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2182         {
2183                 if (r_glsl_offsetmapping.integer)
2184                 {
2185                         switch(rsurface.texture->offsetmapping)
2186                         {
2187                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2188                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2189                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_OFF: break;
2191                         }
2192                 }
2193                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195                 // normalmap (deferred prepass), may use alpha test on diffuse
2196                 mode = SHADERMODE_DEFERREDGEOMETRY;
2197                 GL_BlendFunc(GL_ONE, GL_ZERO);
2198                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2199                 if (vid.allowalphatocoverage)
2200                         GL_AlphaToCoverage(false);
2201         }
2202         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2203         {
2204                 if (r_glsl_offsetmapping.integer)
2205                 {
2206                         switch(rsurface.texture->offsetmapping)
2207                         {
2208                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2209                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2210                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211                         case OFFSETMAPPING_OFF: break;
2212                         }
2213                 }
2214                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2215                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2216                 // light source
2217                 mode = SHADERMODE_LIGHTSOURCE;
2218                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2219                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2220                 if (diffusescale > 0)
2221                         permutation |= SHADERPERMUTATION_DIFFUSE;
2222                 if (specularscale > 0)
2223                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2224                 if (r_refdef.fogenabled)
2225                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2226                 if (rsurface.texture->colormapping)
2227                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2228                 if (r_shadow_usingshadowmap2d)
2229                 {
2230                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2231                         if(r_shadow_shadowmapvsdct)
2232                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2233
2234                         if (r_shadow_shadowmapsampler)
2235                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2236                         if (r_shadow_shadowmappcf > 1)
2237                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2238                         else if (r_shadow_shadowmappcf)
2239                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2240                 }
2241                 if (rsurface.texture->reflectmasktexture)
2242                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2243                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2244                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2245                 if (vid.allowalphatocoverage)
2246                         GL_AlphaToCoverage(false);
2247         }
2248         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2249         {
2250                 if (r_glsl_offsetmapping.integer)
2251                 {
2252                         switch(rsurface.texture->offsetmapping)
2253                         {
2254                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2255                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_OFF: break;
2258                         }
2259                 }
2260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2261                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2262                 // unshaded geometry (fullbright or ambient model lighting)
2263                 mode = SHADERMODE_FLATCOLOR;
2264                 ambientscale = diffusescale = specularscale = 0;
2265                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2266                         permutation |= SHADERPERMUTATION_GLOW;
2267                 if (r_refdef.fogenabled)
2268                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2269                 if (rsurface.texture->colormapping)
2270                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2271                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2272                 {
2273                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2274                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2275
2276                         if (r_shadow_shadowmapsampler)
2277                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2278                         if (r_shadow_shadowmappcf > 1)
2279                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2280                         else if (r_shadow_shadowmappcf)
2281                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2282                 }
2283                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2284                         permutation |= SHADERPERMUTATION_REFLECTION;
2285                 if (rsurface.texture->reflectmasktexture)
2286                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2287                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2288                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289                 // when using alphatocoverage, we don't need alphakill
2290                 if (vid.allowalphatocoverage)
2291                 {
2292                         if (r_transparent_alphatocoverage.integer)
2293                         {
2294                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2295                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2296                         }
2297                         else
2298                                 GL_AlphaToCoverage(false);
2299                 }
2300         }
2301         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2302         {
2303                 if (r_glsl_offsetmapping.integer)
2304                 {
2305                         switch(rsurface.texture->offsetmapping)
2306                         {
2307                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2308                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2309                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310                         case OFFSETMAPPING_OFF: break;
2311                         }
2312                 }
2313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2314                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2315                 // directional model lighting
2316                 mode = SHADERMODE_LIGHTDIRECTION;
2317                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2318                         permutation |= SHADERPERMUTATION_GLOW;
2319                 permutation |= SHADERPERMUTATION_DIFFUSE;
2320                 if (specularscale > 0)
2321                         permutation |= SHADERPERMUTATION_SPECULAR;
2322                 if (r_refdef.fogenabled)
2323                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2324                 if (rsurface.texture->colormapping)
2325                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2326                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2327                 {
2328                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2329                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2330
2331                         if (r_shadow_shadowmapsampler)
2332                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2333                         if (r_shadow_shadowmappcf > 1)
2334                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2335                         else if (r_shadow_shadowmappcf)
2336                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2337                 }
2338                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2339                         permutation |= SHADERPERMUTATION_REFLECTION;
2340                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2341                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2342                 if (rsurface.texture->reflectmasktexture)
2343                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2344                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2345                 {
2346                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2347                         if (r_shadow_bouncegriddirectional)
2348                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2349                 }
2350                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2351                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352                 // when using alphatocoverage, we don't need alphakill
2353                 if (vid.allowalphatocoverage)
2354                 {
2355                         if (r_transparent_alphatocoverage.integer)
2356                         {
2357                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2358                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2359                         }
2360                         else
2361                                 GL_AlphaToCoverage(false);
2362                 }
2363         }
2364         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2365         {
2366                 if (r_glsl_offsetmapping.integer)
2367                 {
2368                         switch(rsurface.texture->offsetmapping)
2369                         {
2370                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2371                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2372                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373                         case OFFSETMAPPING_OFF: break;
2374                         }
2375                 }
2376                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2377                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2378                 // ambient model lighting
2379                 mode = SHADERMODE_LIGHTDIRECTION;
2380                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2381                         permutation |= SHADERPERMUTATION_GLOW;
2382                 if (r_refdef.fogenabled)
2383                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2384                 if (rsurface.texture->colormapping)
2385                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2386                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2387                 {
2388                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2389                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2390
2391                         if (r_shadow_shadowmapsampler)
2392                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2393                         if (r_shadow_shadowmappcf > 1)
2394                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2395                         else if (r_shadow_shadowmappcf)
2396                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2397                 }
2398                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2399                         permutation |= SHADERPERMUTATION_REFLECTION;
2400                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2401                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2402                 if (rsurface.texture->reflectmasktexture)
2403                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2404                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2405                 {
2406                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2407                         if (r_shadow_bouncegriddirectional)
2408                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2409                 }
2410                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2411                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412                 // when using alphatocoverage, we don't need alphakill
2413                 if (vid.allowalphatocoverage)
2414                 {
2415                         if (r_transparent_alphatocoverage.integer)
2416                         {
2417                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2418                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2419                         }
2420                         else
2421                                 GL_AlphaToCoverage(false);
2422                 }
2423         }
2424         else
2425         {
2426                 if (r_glsl_offsetmapping.integer)
2427                 {
2428                         switch(rsurface.texture->offsetmapping)
2429                         {
2430                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2431                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2432                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433                         case OFFSETMAPPING_OFF: break;
2434                         }
2435                 }
2436                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2437                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2438                 // lightmapped wall
2439                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2440                         permutation |= SHADERPERMUTATION_GLOW;
2441                 if (r_refdef.fogenabled)
2442                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2443                 if (rsurface.texture->colormapping)
2444                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2445                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2446                 {
2447                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2448                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2449
2450                         if (r_shadow_shadowmapsampler)
2451                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2452                         if (r_shadow_shadowmappcf > 1)
2453                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2454                         else if (r_shadow_shadowmappcf)
2455                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2456                 }
2457                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2458                         permutation |= SHADERPERMUTATION_REFLECTION;
2459                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2460                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2461                 if (rsurface.texture->reflectmasktexture)
2462                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2463                 if (FAKELIGHT_ENABLED)
2464                 {
2465                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2466                         mode = SHADERMODE_FAKELIGHT;
2467                         permutation |= SHADERPERMUTATION_DIFFUSE;
2468                         if (specularscale > 0)
2469                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2470                 }
2471                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2472                 {
2473                         // deluxemapping (light direction texture)
2474                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2475                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2476                         else
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2478                         permutation |= SHADERPERMUTATION_DIFFUSE;
2479                         if (specularscale > 0)
2480                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2481                 }
2482                 else if (r_glsl_deluxemapping.integer >= 2)
2483                 {
2484                         // fake deluxemapping (uniform light direction in tangentspace)
2485                         if (rsurface.uselightmaptexture)
2486                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2487                         else
2488                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2489                         permutation |= SHADERPERMUTATION_DIFFUSE;
2490                         if (specularscale > 0)
2491                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2492                 }
2493                 else if (rsurface.uselightmaptexture)
2494                 {
2495                         // ordinary lightmapping (q1bsp, q3bsp)
2496                         mode = SHADERMODE_LIGHTMAP;
2497                 }
2498                 else
2499                 {
2500                         // ordinary vertex coloring (q3bsp)
2501                         mode = SHADERMODE_VERTEXCOLOR;
2502                 }
2503                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2504                 {
2505                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2506                         if (r_shadow_bouncegriddirectional)
2507                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2508                 }
2509                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2510                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 // when using alphatocoverage, we don't need alphakill
2512                 if (vid.allowalphatocoverage)
2513                 {
2514                         if (r_transparent_alphatocoverage.integer)
2515                         {
2516                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2517                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2518                         }
2519                         else
2520                                 GL_AlphaToCoverage(false);
2521                 }
2522         }
2523         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2524                 colormod = dummy_colormod;
2525         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2526                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2527         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2528                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2529         switch(vid.renderpath)
2530         {
2531         case RENDERPATH_D3D9:
2532 #ifdef SUPPORTD3D
2533                 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);
2534                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2535                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2536                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2537                 if (mode == SHADERMODE_LIGHTSOURCE)
2538                 {
2539                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2540                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2541                 }
2542                 else
2543                 {
2544                         if (mode == SHADERMODE_LIGHTDIRECTION)
2545                         {
2546                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2547                         }
2548                 }
2549                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2552                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2553                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2554
2555                 if (mode == SHADERMODE_LIGHTSOURCE)
2556                 {
2557                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2562
2563                         // additive passes are only darkened by fog, not tinted
2564                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2565                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2566                 }
2567                 else
2568                 {
2569                         if (mode == SHADERMODE_FLATCOLOR)
2570                         {
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2572                         }
2573                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2574                         {
2575                                 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]);
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[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] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * 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                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2582                         }
2583                         else
2584                         {
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2587                                 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);
2588                                 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);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2590                         }
2591                         // additive passes are only darkened by fog, not tinted
2592                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2594                         else
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2596                         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);
2597                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2604                         if (mode == SHADERMODE_WATER)
2605                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2606                 }
2607                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2608                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2609                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2610                 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));
2611                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2612                 if (rsurface.texture->pantstexture)
2613                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2614                 else
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2616                 if (rsurface.texture->shirttexture)
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2618                 else
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2620                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2621                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2624                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2625                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2626                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2627                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2629                         );
2630                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2631                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2632                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2633
2634                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2635                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2636                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2637                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2638                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2642                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2643                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2644                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2645                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2646                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2647                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2648                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2649                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2650                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2651                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2652                 {
2653                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2654                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2655                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2656                 }
2657                 else
2658                 {
2659                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2660                 }
2661 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2662 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2663                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2665                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2666                 {
2667                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2668                         if (rsurface.rtlight)
2669                         {
2670                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2671                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2672                         }
2673                 }
2674 #endif
2675                 break;
2676         case RENDERPATH_D3D10:
2677                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2678                 break;
2679         case RENDERPATH_D3D11:
2680                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2681                 break;
2682         case RENDERPATH_GL20:
2683         case RENDERPATH_GLES2:
2684                 if (!vid.useinterleavedarrays)
2685                 {
2686                         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);
2687                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2688                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2689                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2694                 }
2695                 else
2696                 {
2697                         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);
2698                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2699                 }
2700                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2701                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2702                 if (mode == SHADERMODE_LIGHTSOURCE)
2703                 {
2704                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2705                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2706                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2707                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2708                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2709                         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);
2710         
2711                         // additive passes are only darkened by fog, not tinted
2712                         if (r_glsl_permutation->loc_FogColor >= 0)
2713                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2714                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2715                 }
2716                 else
2717                 {
2718                         if (mode == SHADERMODE_FLATCOLOR)
2719                         {
2720                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2721                         }
2722                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2723                         {
2724                                 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]);
2725                                 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]);
2726                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2727                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2729                                 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]);
2730                                 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]);
2731                         }
2732                         else
2733                         {
2734                                 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]);
2735                                 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]);
2736                                 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);
2737                                 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);
2738                                 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);
2739                         }
2740                         // additive passes are only darkened by fog, not tinted
2741                         if (r_glsl_permutation->loc_FogColor >= 0)
2742                         {
2743                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2744                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2745                                 else
2746                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2747                         }
2748                         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);
2749                         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]);
2750                         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]);
2751                         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]);
2752                         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]);
2753                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2754                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2756                         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]);
2757                 }
2758                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2759                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2761                 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]);
2762                 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]);
2763
2764                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2765                 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));
2766                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2767                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2768                 {
2769                         if (rsurface.texture->pantstexture)
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2771                         else
2772                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2773                 }
2774                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2775                 {
2776                         if (rsurface.texture->shirttexture)
2777                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2778                         else
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2780                 }
2781                 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]);
2782                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2783                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2784                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2785                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2786                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2787                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2788                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2790                         );
2791                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2792                 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]);
2793                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2794                 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);}
2795                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2796
2797                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2798                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2799                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2800                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2801                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2802                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2803                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2804                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2808                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2809                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2810                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2811                 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);
2812                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2813                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2814                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2815                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2816                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2817                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2818                 {
2819                         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);
2820                         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);
2821                         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);
2822                 }
2823                 else
2824                 {
2825                         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);
2826                 }
2827                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2828                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2829                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2830                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2831                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2832                 {
2833                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2834                         if (rsurface.rtlight)
2835                         {
2836                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2837                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2838                         }
2839                 }
2840                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2841                 CHECKGLERROR
2842                 break;
2843         case RENDERPATH_GL11:
2844         case RENDERPATH_GL13:
2845         case RENDERPATH_GLES1:
2846                 break;
2847         case RENDERPATH_SOFT:
2848                 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);
2849                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2850                 R_SetupShader_SetPermutationSoft(mode, permutation);
2851                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2852                 if (mode == SHADERMODE_LIGHTSOURCE)
2853                 {
2854                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2855                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2860         
2861                         // additive passes are only darkened by fog, not tinted
2862                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2863                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2864                 }
2865                 else
2866                 {
2867                         if (mode == SHADERMODE_FLATCOLOR)
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2870                         }
2871                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2872                         {
2873                                 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]);
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2875                                 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);
2876                                 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);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2878                                 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]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2880                         }
2881                         else
2882                         {
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2885                                 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);
2886                                 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);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2888                         }
2889                         // additive passes are only darkened by fog, not tinted
2890                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2892                         else
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2894                         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);
2895                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2897                         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]);
2898                         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]);
2899                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2902                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2903                 }
2904                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2907                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2908                 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]);
2909
2910                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2911                 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));
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2913                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2914                 {
2915                         if (rsurface.texture->pantstexture)
2916                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2917                         else
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2919                 }
2920                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2921                 {
2922                         if (rsurface.texture->shirttexture)
2923                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2924                         else
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2926                 }
2927                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2928                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2931                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2932                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2933                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2934                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2936                         );
2937                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2938                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2939
2940                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2941                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2942                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2943                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2944                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2945                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2946                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2948                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2949                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2950                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2951                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2952                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2953                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2954                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2955                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2956                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2957                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2958                 {
2959                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2960                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2961                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2962                 }
2963                 else
2964                 {
2965                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2968 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2969                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2970                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2971                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2972                 {
2973                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2974                         if (rsurface.rtlight)
2975                         {
2976                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2977                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2978                         }
2979                 }
2980                 break;
2981         }
2982 }
2983
2984 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2985 {
2986         // select a permutation of the lighting shader appropriate to this
2987         // combination of texture, entity, light source, and fogging, only use the
2988         // minimum features necessary to avoid wasting rendering time in the
2989         // fragment shader on features that are not being used
2990         unsigned int permutation = 0;
2991         unsigned int mode = 0;
2992         const float *lightcolorbase = rtlight->currentcolor;
2993         float ambientscale = rtlight->ambientscale;
2994         float diffusescale = rtlight->diffusescale;
2995         float specularscale = rtlight->specularscale;
2996         // this is the location of the light in view space
2997         vec3_t viewlightorigin;
2998         // this transforms from view space (camera) to light space (cubemap)
2999         matrix4x4_t viewtolight;
3000         matrix4x4_t lighttoview;
3001         float viewtolight16f[16];
3002         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3003         // light source
3004         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3005         if (rtlight->currentcubemap != r_texture_whitecube)
3006                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3007         if (diffusescale > 0)
3008                 permutation |= SHADERPERMUTATION_DIFFUSE;
3009         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3010                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3011         if (r_shadow_usingshadowmap2d)
3012         {
3013                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3014                 if (r_shadow_shadowmapvsdct)
3015                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3016
3017                 if (r_shadow_shadowmapsampler)
3018                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3019                 if (r_shadow_shadowmappcf > 1)
3020                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3021                 else if (r_shadow_shadowmappcf)
3022                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3023         }
3024         if (vid.allowalphatocoverage)
3025                 GL_AlphaToCoverage(false);
3026         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3027         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3028         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3029         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3030         switch(vid.renderpath)
3031         {
3032         case RENDERPATH_D3D9:
3033 #ifdef SUPPORTD3D
3034                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3039                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3040                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3041                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3042                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3043                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3045
3046                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3047                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3048                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3049                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3050                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3051                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3052 #endif
3053                 break;
3054         case RENDERPATH_D3D10:
3055                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_D3D11:
3058                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3059                 break;
3060         case RENDERPATH_GL20:
3061         case RENDERPATH_GLES2:
3062                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3063                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3064                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3065                 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);
3066                 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);
3067                 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);
3068                 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]);
3069                 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]);
3070                 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) - 1.0f);
3071                 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]);
3072                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3073
3074                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3075                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3076                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3077                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3078                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3079                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3080                 break;
3081         case RENDERPATH_GL11:
3082         case RENDERPATH_GL13:
3083         case RENDERPATH_GLES1:
3084                 break;
3085         case RENDERPATH_SOFT:
3086                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3088                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3089                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3090                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3091                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3092                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3093                 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]);
3094                 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) - 1.0f);
3095                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3096                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3097
3098                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3099                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3100                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3101                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3102                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3103                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3104                 break;
3105         }
3106 }
3107
3108 #define SKINFRAME_HASH 1024
3109
3110 typedef struct
3111 {
3112         int loadsequence; // incremented each level change
3113         memexpandablearray_t array;
3114         skinframe_t *hash[SKINFRAME_HASH];
3115 }
3116 r_skinframe_t;
3117 r_skinframe_t r_skinframe;
3118
3119 void R_SkinFrame_PrepareForPurge(void)
3120 {
3121         r_skinframe.loadsequence++;
3122         // wrap it without hitting zero
3123         if (r_skinframe.loadsequence >= 200)
3124                 r_skinframe.loadsequence = 1;
3125 }
3126
3127 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3128 {
3129         if (!skinframe)
3130                 return;
3131         // mark the skinframe as used for the purging code
3132         skinframe->loadsequence = r_skinframe.loadsequence;
3133 }
3134
3135 void R_SkinFrame_Purge(void)
3136 {
3137         int i;
3138         skinframe_t *s;
3139         for (i = 0;i < SKINFRAME_HASH;i++)
3140         {
3141                 for (s = r_skinframe.hash[i];s;s = s->next)
3142                 {
3143                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3144                         {
3145                                 if (s->merged == s->base)
3146                                         s->merged = NULL;
3147                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3148                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3149                                 R_PurgeTexture(s->merged);s->merged = NULL;
3150                                 R_PurgeTexture(s->base  );s->base   = NULL;
3151                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3152                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3153                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3154                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3155                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3156                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3157                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3158                                 s->loadsequence = 0;
3159                         }
3160                 }
3161         }
3162 }
3163
3164 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3165         skinframe_t *item;
3166         char basename[MAX_QPATH];
3167
3168         Image_StripImageExtension(name, basename, sizeof(basename));
3169
3170         if( last == NULL ) {
3171                 int hashindex;
3172                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3173                 item = r_skinframe.hash[hashindex];
3174         } else {
3175                 item = last->next;
3176         }
3177
3178         // linearly search through the hash bucket
3179         for( ; item ; item = item->next ) {
3180                 if( !strcmp( item->basename, basename ) ) {
3181                         return item;
3182                 }
3183         }
3184         return NULL;
3185 }
3186
3187 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3188 {
3189         skinframe_t *item;
3190         int hashindex;
3191         char basename[MAX_QPATH];
3192
3193         Image_StripImageExtension(name, basename, sizeof(basename));
3194
3195         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3196         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3197                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3198                         break;
3199
3200         if (!item) {
3201                 rtexture_t *dyntexture;
3202                 // check whether its a dynamic texture
3203                 dyntexture = CL_GetDynTexture( basename );
3204                 if (!add && !dyntexture)
3205                         return NULL;
3206                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3207                 memset(item, 0, sizeof(*item));
3208                 strlcpy(item->basename, basename, sizeof(item->basename));
3209                 item->base = dyntexture; // either NULL or dyntexture handle
3210                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3211                 item->comparewidth = comparewidth;
3212                 item->compareheight = compareheight;
3213                 item->comparecrc = comparecrc;
3214                 item->next = r_skinframe.hash[hashindex];
3215                 r_skinframe.hash[hashindex] = item;
3216         }
3217         else if (textureflags & TEXF_FORCE_RELOAD)
3218         {
3219                 rtexture_t *dyntexture;
3220                 // check whether its a dynamic texture
3221                 dyntexture = CL_GetDynTexture( basename );
3222                 if (!add && !dyntexture)
3223                         return NULL;
3224                 if (item->merged == item->base)
3225                         item->merged = NULL;
3226                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3227                 R_PurgeTexture(item->stain );item->stain  = NULL;
3228                 R_PurgeTexture(item->merged);item->merged = NULL;
3229                 R_PurgeTexture(item->base  );item->base   = NULL;
3230                 R_PurgeTexture(item->pants );item->pants  = NULL;
3231                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3232                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3233                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3234                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3235                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3236         R_PurgeTexture(item->reflect);item->reflect = NULL;
3237                 item->loadsequence = 0;
3238         }
3239         else if( item->base == NULL )
3240         {
3241                 rtexture_t *dyntexture;
3242                 // check whether its a dynamic texture
3243                 // 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]
3244                 dyntexture = CL_GetDynTexture( basename );
3245                 item->base = dyntexture; // either NULL or dyntexture handle
3246         }
3247
3248         R_SkinFrame_MarkUsed(item);
3249         return item;
3250 }
3251
3252 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3253         { \
3254                 unsigned long long avgcolor[5], wsum; \
3255                 int pix, comp, w; \
3256                 avgcolor[0] = 0; \
3257                 avgcolor[1] = 0; \
3258                 avgcolor[2] = 0; \
3259                 avgcolor[3] = 0; \
3260                 avgcolor[4] = 0; \
3261                 wsum = 0; \
3262                 for(pix = 0; pix < cnt; ++pix) \
3263                 { \
3264                         w = 0; \
3265                         for(comp = 0; comp < 3; ++comp) \
3266                                 w += getpixel; \
3267                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3268                         { \
3269                                 ++wsum; \
3270                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3271                                 w = getpixel; \
3272                                 for(comp = 0; comp < 3; ++comp) \
3273                                         avgcolor[comp] += getpixel * w; \
3274                                 avgcolor[3] += w; \
3275                         } \
3276                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3277                         avgcolor[4] += getpixel; \
3278                 } \
3279                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3280                         avgcolor[3] = 1; \
3281                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3282                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3283                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3284                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3285         }
3286
3287 extern cvar_t gl_picmip;
3288 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3289 {
3290         int j;
3291         unsigned char *pixels;
3292         unsigned char *bumppixels;
3293         unsigned char *basepixels = NULL;
3294         int basepixels_width = 0;
3295         int basepixels_height = 0;
3296         skinframe_t *skinframe;
3297         rtexture_t *ddsbase = NULL;
3298         qboolean ddshasalpha = false;
3299         float ddsavgcolor[4];
3300         char basename[MAX_QPATH];
3301         int miplevel = R_PicmipForFlags(textureflags);
3302         int savemiplevel = miplevel;
3303         int mymiplevel;
3304
3305         if (cls.state == ca_dedicated)
3306                 return NULL;
3307
3308         // return an existing skinframe if already loaded
3309         // if loading of the first image fails, don't make a new skinframe as it
3310         // would cause all future lookups of this to be missing
3311         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3312         if (skinframe && skinframe->base)
3313                 return skinframe;
3314
3315         Image_StripImageExtension(name, basename, sizeof(basename));
3316
3317         // check for DDS texture file first
3318         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3319         {
3320                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3321                 if (basepixels == NULL)
3322                         return NULL;
3323         }
3324
3325         // FIXME handle miplevel
3326
3327         if (developer_loading.integer)
3328                 Con_Printf("loading skin \"%s\"\n", name);
3329
3330         // we've got some pixels to store, so really allocate this new texture now
3331         if (!skinframe)
3332                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3333         textureflags &= ~TEXF_FORCE_RELOAD;
3334         skinframe->stain = NULL;
3335         skinframe->merged = NULL;
3336         skinframe->base = NULL;
3337         skinframe->pants = NULL;
3338         skinframe->shirt = NULL;
3339         skinframe->nmap = NULL;
3340         skinframe->gloss = NULL;
3341         skinframe->glow = NULL;
3342         skinframe->fog = NULL;
3343         skinframe->reflect = NULL;
3344         skinframe->hasalpha = false;
3345
3346         if (ddsbase)
3347         {
3348                 skinframe->base = ddsbase;
3349                 skinframe->hasalpha = ddshasalpha;
3350                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3351                 if (r_loadfog && skinframe->hasalpha)
3352                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3353                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3354         }
3355         else
3356         {
3357                 basepixels_width = image_width;
3358                 basepixels_height = image_height;
3359                 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);
3360                 if (textureflags & TEXF_ALPHA)
3361                 {
3362                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3363                         {
3364                                 if (basepixels[j] < 255)
3365                                 {
3366                                         skinframe->hasalpha = true;
3367                                         break;
3368                                 }
3369                         }
3370                         if (r_loadfog && skinframe->hasalpha)
3371                         {
3372                                 // has transparent pixels
3373                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3374                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3375                                 {
3376                                         pixels[j+0] = 255;
3377                                         pixels[j+1] = 255;
3378                                         pixels[j+2] = 255;
3379                                         pixels[j+3] = basepixels[j+3];
3380                                 }
3381                                 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);
3382                                 Mem_Free(pixels);
3383                         }
3384                 }
3385                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3386 #ifndef USE_GLES2
3387                 //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]);
3388                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3389                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3391                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3392 #endif
3393         }
3394
3395         if (r_loaddds)
3396         {
3397                 mymiplevel = savemiplevel;
3398                 if (r_loadnormalmap)
3399                         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);
3400                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3401                 if (r_loadgloss)
3402                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3403                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3404                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3405                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3406         }
3407
3408         // _norm is the name used by tenebrae and has been adopted as standard
3409         if (r_loadnormalmap && skinframe->nmap == NULL)
3410         {
3411                 mymiplevel = savemiplevel;
3412                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3413                 {
3414                         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);
3415                         Mem_Free(pixels);
3416                         pixels = NULL;
3417                 }
3418                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3419                 {
3420                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3421                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3422                         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);
3423                         Mem_Free(pixels);
3424                         Mem_Free(bumppixels);
3425                 }
3426                 else if (r_shadow_bumpscale_basetexture.value > 0)
3427                 {
3428                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3429                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3430                         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);
3431                         Mem_Free(pixels);
3432                 }
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3435                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437         }
3438
3439         // _luma is supported only for tenebrae compatibility
3440         // _glow is the preferred name
3441         mymiplevel = savemiplevel;
3442         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))))
3443         {
3444                 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);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3447                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 #endif
3449                 Mem_Free(pixels);pixels = NULL;
3450         }
3451
3452         mymiplevel = savemiplevel;
3453         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3454         {
3455                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3456 #ifndef USE_GLES2
3457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3458                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3459 #endif
3460                 Mem_Free(pixels);
3461                 pixels = NULL;
3462         }
3463
3464         mymiplevel = savemiplevel;
3465         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3466         {
3467                 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);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3470                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3471 #endif
3472                 Mem_Free(pixels);
3473                 pixels = NULL;
3474         }
3475
3476         mymiplevel = savemiplevel;
3477         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3478         {
3479                 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);
3480 #ifndef USE_GLES2
3481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3482                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3483 #endif
3484                 Mem_Free(pixels);
3485                 pixels = NULL;
3486         }
3487
3488         mymiplevel = savemiplevel;
3489         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3490         {
3491                 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);
3492 #ifndef USE_GLES2
3493                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3494                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3495 #endif
3496                 Mem_Free(pixels);
3497                 pixels = NULL;
3498         }
3499
3500         if (basepixels)
3501                 Mem_Free(basepixels);
3502
3503         return skinframe;
3504 }
3505
3506 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3507 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3508 {
3509         int i;
3510         unsigned char *temp1, *temp2;
3511         skinframe_t *skinframe;
3512
3513         if (cls.state == ca_dedicated)
3514                 return NULL;
3515
3516         // if already loaded just return it, otherwise make a new skinframe
3517         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3518         if (skinframe && skinframe->base)
3519                 return skinframe;
3520         textureflags &= ~TEXF_FORCE_RELOAD;
3521
3522         skinframe->stain = NULL;
3523         skinframe->merged = NULL;
3524         skinframe->base = NULL;
3525         skinframe->pants = NULL;
3526         skinframe->shirt = NULL;
3527         skinframe->nmap = NULL;
3528         skinframe->gloss = NULL;
3529         skinframe->glow = NULL;
3530         skinframe->fog = NULL;
3531         skinframe->reflect = NULL;
3532         skinframe->hasalpha = false;
3533
3534         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3535         if (!skindata)
3536                 return NULL;
3537
3538         if (developer_loading.integer)
3539                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3540
3541         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3542         {
3543                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3544                 temp2 = temp1 + width * height * 4;
3545                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3546                 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);
3547                 Mem_Free(temp1);
3548         }
3549         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3550         if (textureflags & TEXF_ALPHA)
3551         {
3552                 for (i = 3;i < width * height * 4;i += 4)
3553                 {
3554                         if (skindata[i] < 255)
3555                         {
3556                                 skinframe->hasalpha = true;
3557                                 break;
3558                         }
3559                 }
3560                 if (r_loadfog && skinframe->hasalpha)
3561                 {
3562                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3563                         memcpy(fogpixels, skindata, width * height * 4);
3564                         for (i = 0;i < width * height * 4;i += 4)
3565                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3566                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3567                         Mem_Free(fogpixels);
3568                 }
3569         }
3570
3571         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3572         //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]);
3573
3574         return skinframe;
3575 }
3576
3577 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3578 {
3579         int i;
3580         int featuresmask;
3581         skinframe_t *skinframe;
3582
3583         if (cls.state == ca_dedicated)
3584                 return NULL;
3585
3586         // if already loaded just return it, otherwise make a new skinframe
3587         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3588         if (skinframe && skinframe->base)
3589                 return skinframe;
3590         textureflags &= ~TEXF_FORCE_RELOAD;
3591
3592         skinframe->stain = NULL;
3593         skinframe->merged = NULL;
3594         skinframe->base = NULL;
3595         skinframe->pants = NULL;
3596         skinframe->shirt = NULL;
3597         skinframe->nmap = NULL;
3598         skinframe->gloss = NULL;
3599         skinframe->glow = NULL;
3600         skinframe->fog = NULL;
3601         skinframe->reflect = NULL;
3602         skinframe->hasalpha = false;
3603
3604         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3605         if (!skindata)
3606                 return NULL;
3607
3608         if (developer_loading.integer)
3609                 Con_Printf("loading quake skin \"%s\"\n", name);
3610
3611         // 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)
3612         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3613         memcpy(skinframe->qpixels, skindata, width*height);
3614         skinframe->qwidth = width;
3615         skinframe->qheight = height;
3616
3617         featuresmask = 0;
3618         for (i = 0;i < width * height;i++)
3619                 featuresmask |= palette_featureflags[skindata[i]];
3620
3621         skinframe->hasalpha = false;
3622         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3623         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3624         skinframe->qgeneratemerged = true;
3625         skinframe->qgeneratebase = skinframe->qhascolormapping;
3626         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3627
3628         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3629         //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]);
3630
3631         return skinframe;
3632 }
3633
3634 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3635 {
3636         int width;
3637         int height;
3638         unsigned char *skindata;
3639
3640         if (!skinframe->qpixels)
3641                 return;
3642
3643         if (!skinframe->qhascolormapping)
3644                 colormapped = false;
3645
3646         if (colormapped)
3647         {
3648                 if (!skinframe->qgeneratebase)
3649                         return;
3650         }
3651         else
3652         {
3653                 if (!skinframe->qgeneratemerged)
3654                         return;
3655         }
3656
3657         width = skinframe->qwidth;
3658         height = skinframe->qheight;
3659         skindata = skinframe->qpixels;
3660
3661         if (skinframe->qgeneratenmap)
3662         {
3663                 unsigned char *temp1, *temp2;
3664                 skinframe->qgeneratenmap = false;
3665                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3666                 temp2 = temp1 + width * height * 4;
3667                 // use either a custom palette or the quake palette
3668                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3669                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3670                 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);
3671                 Mem_Free(temp1);
3672         }
3673
3674         if (skinframe->qgenerateglow)
3675         {
3676                 skinframe->qgenerateglow = false;
3677                 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
3678         }
3679
3680         if (colormapped)
3681         {
3682                 skinframe->qgeneratebase = false;
3683                 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);
3684                 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);
3685                 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);
3686         }
3687         else
3688         {
3689                 skinframe->qgeneratemerged = false;
3690                 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);
3691         }
3692
3693         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3694         {
3695                 Mem_Free(skinframe->qpixels);
3696                 skinframe->qpixels = NULL;
3697         }
3698 }
3699
3700 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)
3701 {
3702         int i;
3703         skinframe_t *skinframe;
3704
3705         if (cls.state == ca_dedicated)
3706                 return NULL;
3707
3708         // if already loaded just return it, otherwise make a new skinframe
3709         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3710         if (skinframe && skinframe->base)
3711                 return skinframe;
3712         textureflags &= ~TEXF_FORCE_RELOAD;
3713
3714         skinframe->stain = NULL;
3715         skinframe->merged = NULL;
3716         skinframe->base = NULL;
3717         skinframe->pants = NULL;
3718         skinframe->shirt = NULL;
3719         skinframe->nmap = NULL;
3720         skinframe->gloss = NULL;
3721         skinframe->glow = NULL;
3722         skinframe->fog = NULL;
3723         skinframe->reflect = NULL;
3724         skinframe->hasalpha = false;
3725
3726         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3727         if (!skindata)
3728                 return NULL;
3729
3730         if (developer_loading.integer)
3731                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3732
3733         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3734         if (textureflags & TEXF_ALPHA)
3735         {
3736                 for (i = 0;i < width * height;i++)
3737                 {
3738                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3739                         {
3740                                 skinframe->hasalpha = true;
3741                                 break;
3742                         }
3743                 }
3744                 if (r_loadfog && skinframe->hasalpha)
3745                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3746         }
3747
3748         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3749         //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]);
3750
3751         return skinframe;
3752 }
3753
3754 skinframe_t *R_SkinFrame_LoadMissing(void)
3755 {
3756         skinframe_t *skinframe;
3757
3758         if (cls.state == ca_dedicated)
3759                 return NULL;
3760
3761         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3762         skinframe->stain = NULL;
3763         skinframe->merged = NULL;
3764         skinframe->base = NULL;
3765         skinframe->pants = NULL;
3766         skinframe->shirt = NULL;
3767         skinframe->nmap = NULL;
3768         skinframe->gloss = NULL;
3769         skinframe->glow = NULL;
3770         skinframe->fog = NULL;
3771         skinframe->reflect = NULL;
3772         skinframe->hasalpha = false;
3773
3774         skinframe->avgcolor[0] = rand() / RAND_MAX;
3775         skinframe->avgcolor[1] = rand() / RAND_MAX;
3776         skinframe->avgcolor[2] = rand() / RAND_MAX;
3777         skinframe->avgcolor[3] = 1;
3778
3779         return skinframe;
3780 }
3781
3782 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3783 typedef struct suffixinfo_s
3784 {
3785         const char *suffix;
3786         qboolean flipx, flipy, flipdiagonal;
3787 }
3788 suffixinfo_t;
3789 static suffixinfo_t suffix[3][6] =
3790 {
3791         {
3792                 {"px",   false, false, false},
3793                 {"nx",   false, false, false},
3794                 {"py",   false, false, false},
3795                 {"ny",   false, false, false},
3796                 {"pz",   false, false, false},
3797                 {"nz",   false, false, false}
3798         },
3799         {
3800                 {"posx", false, false, false},
3801                 {"negx", false, false, false},
3802                 {"posy", false, false, false},
3803                 {"negy", false, false, false},
3804                 {"posz", false, false, false},
3805                 {"negz", false, false, false}
3806         },
3807         {
3808                 {"rt",    true, false,  true},
3809                 {"lf",   false,  true,  true},
3810                 {"ft",    true,  true, false},
3811                 {"bk",   false, false, false},
3812                 {"up",    true, false,  true},
3813                 {"dn",    true, false,  true}
3814         }
3815 };
3816
3817 static int componentorder[4] = {0, 1, 2, 3};
3818
3819 rtexture_t *R_LoadCubemap(const char *basename)
3820 {
3821         int i, j, cubemapsize;
3822         unsigned char *cubemappixels, *image_buffer;
3823         rtexture_t *cubemaptexture;
3824         char name[256];
3825         // must start 0 so the first loadimagepixels has no requested width/height
3826         cubemapsize = 0;
3827         cubemappixels = NULL;
3828         cubemaptexture = NULL;
3829         // keep trying different suffix groups (posx, px, rt) until one loads
3830         for (j = 0;j < 3 && !cubemappixels;j++)
3831         {
3832                 // load the 6 images in the suffix group
3833                 for (i = 0;i < 6;i++)
3834                 {
3835                         // generate an image name based on the base and and suffix
3836                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3837                         // load it
3838                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3839                         {
3840                                 // an image loaded, make sure width and height are equal
3841                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3842                                 {
3843                                         // if this is the first image to load successfully, allocate the cubemap memory
3844                                         if (!cubemappixels && image_width >= 1)
3845                                         {
3846                                                 cubemapsize = image_width;
3847                                                 // note this clears to black, so unavailable sides are black
3848                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3849                                         }
3850                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3851                                         if (cubemappixels)
3852                                                 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);
3853                                 }
3854                                 else
3855                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3856                                 // free the image
3857                                 Mem_Free(image_buffer);
3858                         }
3859                 }
3860         }
3861         // if a cubemap loaded, upload it
3862         if (cubemappixels)
3863         {
3864                 if (developer_loading.integer)
3865                         Con_Printf("loading cubemap \"%s\"\n", basename);
3866
3867                 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);
3868                 Mem_Free(cubemappixels);
3869         }
3870         else
3871         {
3872                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3873                 if (developer_loading.integer)
3874                 {
3875                         Con_Printf("(tried tried images ");
3876                         for (j = 0;j < 3;j++)
3877                                 for (i = 0;i < 6;i++)
3878                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3879                         Con_Print(" and was unable to find any of them).\n");
3880                 }
3881         }
3882         return cubemaptexture;
3883 }
3884
3885 rtexture_t *R_GetCubemap(const char *basename)
3886 {
3887         int i;
3888         for (i = 0;i < r_texture_numcubemaps;i++)
3889                 if (r_texture_cubemaps[i] != NULL)
3890                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3891                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3892         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3893                 return r_texture_whitecube;
3894         r_texture_numcubemaps++;
3895         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3896         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3897         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3898         return r_texture_cubemaps[i]->texture;
3899 }
3900
3901 void R_FreeCubemap(const char *basename)
3902 {
3903         int i;
3904
3905         for (i = 0;i < r_texture_numcubemaps;i++)
3906         {
3907                 if (r_texture_cubemaps[i] != NULL)
3908                 {
3909                         if (r_texture_cubemaps[i]->texture)
3910                         {
3911                                 if (developer_loading.integer)
3912                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3913                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3914                                 Mem_Free(r_texture_cubemaps[i]);
3915                                 r_texture_cubemaps[i] = NULL;
3916                         }
3917                 }
3918         }
3919 }
3920
3921 void R_FreeCubemaps(void)
3922 {
3923         int i;
3924         for (i = 0;i < r_texture_numcubemaps;i++)
3925         {
3926                 if (developer_loading.integer)
3927                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3928                 if (r_texture_cubemaps[i] != NULL)
3929                 {
3930                         if (r_texture_cubemaps[i]->texture)
3931                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3932                         Mem_Free(r_texture_cubemaps[i]);
3933                 }
3934         }
3935         r_texture_numcubemaps = 0;
3936 }
3937
3938 void R_Main_FreeViewCache(void)
3939 {
3940         if (r_refdef.viewcache.entityvisible)
3941                 Mem_Free(r_refdef.viewcache.entityvisible);
3942         if (r_refdef.viewcache.world_pvsbits)
3943                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3944         if (r_refdef.viewcache.world_leafvisible)
3945                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3946         if (r_refdef.viewcache.world_surfacevisible)
3947                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3948         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3949 }
3950
3951 void R_Main_ResizeViewCache(void)
3952 {
3953         int numentities = r_refdef.scene.numentities;
3954         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3955         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3956         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3957         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3958         if (r_refdef.viewcache.maxentities < numentities)
3959         {
3960                 r_refdef.viewcache.maxentities = numentities;
3961                 if (r_refdef.viewcache.entityvisible)
3962                         Mem_Free(r_refdef.viewcache.entityvisible);
3963                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3964         }
3965         if (r_refdef.viewcache.world_numclusters != numclusters)
3966         {
3967                 r_refdef.viewcache.world_numclusters = numclusters;
3968                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3969                 if (r_refdef.viewcache.world_pvsbits)
3970                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3971                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3972         }
3973         if (r_refdef.viewcache.world_numleafs != numleafs)
3974         {
3975                 r_refdef.viewcache.world_numleafs = numleafs;
3976                 if (r_refdef.viewcache.world_leafvisible)
3977                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3978                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3979         }
3980         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3981         {
3982                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3983                 if (r_refdef.viewcache.world_surfacevisible)
3984                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3985                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3986         }
3987 }
3988
3989 extern rtexture_t *loadingscreentexture;
3990 void gl_main_start(void)
3991 {
3992         loadingscreentexture = NULL;
3993         r_texture_blanknormalmap = NULL;
3994         r_texture_white = NULL;
3995         r_texture_grey128 = NULL;
3996         r_texture_black = NULL;
3997         r_texture_whitecube = NULL;
3998         r_texture_normalizationcube = NULL;
3999         r_texture_fogattenuation = NULL;
4000         r_texture_fogheighttexture = NULL;
4001         r_texture_gammaramps = NULL;
4002         r_texture_numcubemaps = 0;
4003
4004         r_loaddds = r_texture_dds_load.integer != 0;
4005         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4006
4007         switch(vid.renderpath)
4008         {
4009         case RENDERPATH_GL20:
4010         case RENDERPATH_D3D9:
4011         case RENDERPATH_D3D10:
4012         case RENDERPATH_D3D11:
4013         case RENDERPATH_SOFT:
4014         case RENDERPATH_GLES2:
4015                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4016                 Cvar_SetValueQuick(&gl_combine, 1);
4017                 Cvar_SetValueQuick(&r_glsl, 1);
4018                 r_loadnormalmap = true;
4019                 r_loadgloss = true;
4020                 r_loadfog = false;
4021                 break;
4022         case RENDERPATH_GL13:
4023         case RENDERPATH_GLES1:
4024                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4025                 Cvar_SetValueQuick(&gl_combine, 1);
4026                 Cvar_SetValueQuick(&r_glsl, 0);
4027                 r_loadnormalmap = false;
4028                 r_loadgloss = false;
4029                 r_loadfog = true;
4030                 break;
4031         case RENDERPATH_GL11:
4032                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4033                 Cvar_SetValueQuick(&gl_combine, 0);
4034                 Cvar_SetValueQuick(&r_glsl, 0);
4035                 r_loadnormalmap = false;
4036                 r_loadgloss = false;
4037                 r_loadfog = true;
4038                 break;
4039         }
4040
4041         R_AnimCache_Free();
4042         R_FrameData_Reset();
4043
4044         r_numqueries = 0;
4045         r_maxqueries = 0;
4046         memset(r_queries, 0, sizeof(r_queries));
4047
4048         r_qwskincache = NULL;
4049         r_qwskincache_size = 0;
4050
4051         // due to caching of texture_t references, the collision cache must be reset
4052         Collision_Cache_Reset(true);
4053
4054         // set up r_skinframe loading system for textures
4055         memset(&r_skinframe, 0, sizeof(r_skinframe));
4056         r_skinframe.loadsequence = 1;
4057         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4058
4059         r_main_texturepool = R_AllocTexturePool();
4060         R_BuildBlankTextures();
4061         R_BuildNoTexture();
4062         if (vid.support.arb_texture_cube_map)
4063         {
4064                 R_BuildWhiteCube();
4065                 R_BuildNormalizationCube();
4066         }
4067         r_texture_fogattenuation = NULL;
4068         r_texture_fogheighttexture = NULL;
4069         r_texture_gammaramps = NULL;
4070         //r_texture_fogintensity = NULL;
4071         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4072         memset(&r_waterstate, 0, sizeof(r_waterstate));
4073         r_glsl_permutation = NULL;
4074         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4075         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4076         glslshaderstring = NULL;
4077 #ifdef SUPPORTD3D
4078         r_hlsl_permutation = NULL;
4079         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4080         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4081 #endif
4082         hlslshaderstring = NULL;
4083         memset(&r_svbsp, 0, sizeof (r_svbsp));
4084
4085         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4086         r_texture_numcubemaps = 0;
4087
4088         r_refdef.fogmasktable_density = 0;
4089 }
4090
4091 void gl_main_shutdown(void)
4092 {
4093         R_AnimCache_Free();
4094         R_FrameData_Reset();
4095
4096         R_Main_FreeViewCache();
4097
4098         switch(vid.renderpath)
4099         {
4100         case RENDERPATH_GL11:
4101         case RENDERPATH_GL13:
4102         case RENDERPATH_GL20:
4103         case RENDERPATH_GLES1:
4104         case RENDERPATH_GLES2:
4105 #ifdef GL_SAMPLES_PASSED_ARB
4106                 if (r_maxqueries)
4107                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4108 #endif
4109                 break;
4110         case RENDERPATH_D3D9:
4111                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4112                 break;
4113         case RENDERPATH_D3D10:
4114                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4115                 break;
4116         case RENDERPATH_D3D11:
4117                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4118                 break;
4119         case RENDERPATH_SOFT:
4120                 break;
4121         }
4122
4123         r_numqueries = 0;
4124         r_maxqueries = 0;
4125         memset(r_queries, 0, sizeof(r_queries));
4126
4127         r_qwskincache = NULL;
4128         r_qwskincache_size = 0;
4129
4130         // clear out the r_skinframe state
4131         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4132         memset(&r_skinframe, 0, sizeof(r_skinframe));
4133
4134         if (r_svbsp.nodes)
4135                 Mem_Free(r_svbsp.nodes);
4136         memset(&r_svbsp, 0, sizeof (r_svbsp));
4137         R_FreeTexturePool(&r_main_texturepool);
4138         loadingscreentexture = NULL;
4139         r_texture_blanknormalmap = NULL;
4140         r_texture_white = NULL;
4141         r_texture_grey128 = NULL;
4142         r_texture_black = NULL;
4143         r_texture_whitecube = NULL;
4144         r_texture_normalizationcube = NULL;
4145         r_texture_fogattenuation = NULL;
4146         r_texture_fogheighttexture = NULL;
4147         r_texture_gammaramps = NULL;
4148         r_texture_numcubemaps = 0;
4149         //r_texture_fogintensity = NULL;
4150         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4151         memset(&r_waterstate, 0, sizeof(r_waterstate));
4152         R_GLSL_Restart_f();
4153
4154         r_glsl_permutation = NULL;
4155         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4156         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4157         glslshaderstring = NULL;
4158 #ifdef SUPPORTD3D
4159         r_hlsl_permutation = NULL;
4160         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4161         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4162 #endif
4163         hlslshaderstring = NULL;
4164 }
4165
4166 extern void CL_ParseEntityLump(char *entitystring);
4167 void gl_main_newmap(void)
4168 {
4169         // FIXME: move this code to client
4170         char *entities, entname[MAX_QPATH];
4171         if (r_qwskincache)
4172                 Mem_Free(r_qwskincache);
4173         r_qwskincache = NULL;
4174         r_qwskincache_size = 0;
4175         if (cl.worldmodel)
4176         {
4177                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4178                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4179                 {
4180                         CL_ParseEntityLump(entities);
4181                         Mem_Free(entities);
4182                         return;
4183                 }
4184                 if (cl.worldmodel->brush.entities)
4185                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4186         }
4187         R_Main_FreeViewCache();
4188
4189         R_FrameData_Reset();
4190 }
4191
4192 void GL_Main_Init(void)
4193 {
4194         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4195
4196         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4197         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4198         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4199         if (gamemode == GAME_NEHAHRA)
4200         {
4201                 Cvar_RegisterVariable (&gl_fogenable);
4202                 Cvar_RegisterVariable (&gl_fogdensity);
4203                 Cvar_RegisterVariable (&gl_fogred);
4204                 Cvar_RegisterVariable (&gl_foggreen);
4205                 Cvar_RegisterVariable (&gl_fogblue);
4206                 Cvar_RegisterVariable (&gl_fogstart);
4207                 Cvar_RegisterVariable (&gl_fogend);
4208                 Cvar_RegisterVariable (&gl_skyclip);
4209         }
4210         Cvar_RegisterVariable(&r_motionblur);
4211         Cvar_RegisterVariable(&r_damageblur);
4212         Cvar_RegisterVariable(&r_motionblur_averaging);
4213         Cvar_RegisterVariable(&r_motionblur_randomize);
4214         Cvar_RegisterVariable(&r_motionblur_minblur);
4215         Cvar_RegisterVariable(&r_motionblur_maxblur);
4216         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4217         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4218         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4219         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4220         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4221         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4222         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4223         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4224         Cvar_RegisterVariable(&r_equalize_entities_by);
4225         Cvar_RegisterVariable(&r_equalize_entities_to);
4226         Cvar_RegisterVariable(&r_depthfirst);
4227         Cvar_RegisterVariable(&r_useinfinitefarclip);
4228         Cvar_RegisterVariable(&r_farclip_base);
4229         Cvar_RegisterVariable(&r_farclip_world);
4230         Cvar_RegisterVariable(&r_nearclip);
4231         Cvar_RegisterVariable(&r_deformvertexes);
4232         Cvar_RegisterVariable(&r_transparent);
4233         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4234         Cvar_RegisterVariable(&r_showoverdraw);
4235         Cvar_RegisterVariable(&r_showbboxes);
4236         Cvar_RegisterVariable(&r_showsurfaces);
4237         Cvar_RegisterVariable(&r_showtris);
4238         Cvar_RegisterVariable(&r_shownormals);
4239         Cvar_RegisterVariable(&r_showlighting);
4240         Cvar_RegisterVariable(&r_showshadowvolumes);
4241         Cvar_RegisterVariable(&r_showcollisionbrushes);
4242         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4243         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4244         Cvar_RegisterVariable(&r_showdisabledepthtest);
4245         Cvar_RegisterVariable(&r_drawportals);
4246         Cvar_RegisterVariable(&r_drawentities);
4247         Cvar_RegisterVariable(&r_draw2d);
4248         Cvar_RegisterVariable(&r_drawworld);
4249         Cvar_RegisterVariable(&r_cullentities_trace);
4250         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4251         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4252         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4253         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4254         Cvar_RegisterVariable(&r_sortentities);
4255         Cvar_RegisterVariable(&r_drawviewmodel);
4256         Cvar_RegisterVariable(&r_drawexteriormodel);
4257         Cvar_RegisterVariable(&r_speeds);
4258         Cvar_RegisterVariable(&r_fullbrights);
4259         Cvar_RegisterVariable(&r_wateralpha);
4260         Cvar_RegisterVariable(&r_dynamic);
4261         Cvar_RegisterVariable(&r_fakelight);
4262         Cvar_RegisterVariable(&r_fakelight_intensity);
4263         Cvar_RegisterVariable(&r_fullbright);
4264         Cvar_RegisterVariable(&r_shadows);
4265         Cvar_RegisterVariable(&r_shadows_darken);
4266         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4267         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4268         Cvar_RegisterVariable(&r_shadows_throwdistance);
4269         Cvar_RegisterVariable(&r_shadows_throwdirection);
4270         Cvar_RegisterVariable(&r_shadows_focus);
4271         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4272         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4273         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4274         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4275         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4276         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4277         Cvar_RegisterVariable(&r_fog_exp2);
4278         Cvar_RegisterVariable(&r_fog_clear);
4279         Cvar_RegisterVariable(&r_drawfog);
4280         Cvar_RegisterVariable(&r_transparentdepthmasking);
4281         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4282         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4283         Cvar_RegisterVariable(&r_texture_dds_load);
4284         Cvar_RegisterVariable(&r_texture_dds_save);
4285         Cvar_RegisterVariable(&r_textureunits);
4286         Cvar_RegisterVariable(&gl_combine);
4287         Cvar_RegisterVariable(&r_viewfbo);
4288         Cvar_RegisterVariable(&r_viewscale);
4289         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4290         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4291         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4292         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4293         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4294         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4295         Cvar_RegisterVariable(&r_glsl);
4296         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4297         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4298         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4299         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4300         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4301         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4302         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4303         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4304         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4305         Cvar_RegisterVariable(&r_glsl_postprocess);
4306         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4307         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4308         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4309         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4310         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4311         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4312         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4313         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4314
4315         Cvar_RegisterVariable(&r_water);
4316         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4317         Cvar_RegisterVariable(&r_water_clippingplanebias);
4318         Cvar_RegisterVariable(&r_water_refractdistort);
4319         Cvar_RegisterVariable(&r_water_reflectdistort);
4320         Cvar_RegisterVariable(&r_water_scissormode);
4321         Cvar_RegisterVariable(&r_water_lowquality);
4322
4323         Cvar_RegisterVariable(&r_lerpsprites);
4324         Cvar_RegisterVariable(&r_lerpmodels);
4325         Cvar_RegisterVariable(&r_lerplightstyles);
4326         Cvar_RegisterVariable(&r_waterscroll);
4327         Cvar_RegisterVariable(&r_bloom);
4328         Cvar_RegisterVariable(&r_bloom_colorscale);
4329         Cvar_RegisterVariable(&r_bloom_brighten);
4330         Cvar_RegisterVariable(&r_bloom_blur);
4331         Cvar_RegisterVariable(&r_bloom_resolution);
4332         Cvar_RegisterVariable(&r_bloom_colorexponent);
4333         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4334         Cvar_RegisterVariable(&r_hdr);
4335         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4336         Cvar_RegisterVariable(&r_hdr_glowintensity);
4337         Cvar_RegisterVariable(&r_hdr_range);
4338         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4339         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4340         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4341         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4342         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4343         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4344         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4345         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4346         Cvar_RegisterVariable(&developer_texturelogging);
4347         Cvar_RegisterVariable(&gl_lightmaps);
4348         Cvar_RegisterVariable(&r_test);
4349         Cvar_RegisterVariable(&r_glsl_saturation);
4350         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4351         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4352         Cvar_RegisterVariable(&r_framedatasize);
4353         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4354                 Cvar_SetValue("r_fullbrights", 0);
4355         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4356 }
4357
4358 extern void R_Textures_Init(void);
4359 extern void GL_Draw_Init(void);
4360 extern void GL_Main_Init(void);
4361 extern void R_Shadow_Init(void);
4362 extern void R_Sky_Init(void);
4363 extern void GL_Surf_Init(void);
4364 extern void R_Particles_Init(void);
4365 extern void R_Explosion_Init(void);
4366 extern void gl_backend_init(void);
4367 extern void Sbar_Init(void);
4368 extern void R_LightningBeams_Init(void);
4369 extern void Mod_RenderInit(void);
4370 extern void Font_Init(void);
4371
4372 void Render_Init(void)
4373 {
4374         gl_backend_init();
4375         R_Textures_Init();
4376         GL_Main_Init();
4377         Font_Init();
4378         GL_Draw_Init();
4379         R_Shadow_Init();
4380         R_Sky_Init();
4381         GL_Surf_Init();
4382         Sbar_Init();
4383         R_Particles_Init();
4384         R_Explosion_Init();
4385         R_LightningBeams_Init();
4386         Mod_RenderInit();
4387 }
4388
4389 /*
4390 ===============
4391 GL_Init
4392 ===============
4393 */
4394 #ifndef USE_GLES2
4395 extern char *ENGINE_EXTENSIONS;
4396 void GL_Init (void)
4397 {
4398         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4399         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4400         gl_version = (const char *)qglGetString(GL_VERSION);
4401         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4402
4403         if (!gl_extensions)
4404                 gl_extensions = "";
4405         if (!gl_platformextensions)
4406                 gl_platformextensions = "";
4407
4408         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4409         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4410         Con_Printf("GL_VERSION: %s\n", gl_version);
4411         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4412         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4413
4414         VID_CheckExtensions();
4415
4416         // LordHavoc: report supported extensions
4417         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4418
4419         // clear to black (loading plaque will be seen over this)
4420         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4421 }
4422 #endif
4423
4424 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4425 {
4426         int i;
4427         mplane_t *p;
4428         if (r_trippy.integer)
4429                 return false;
4430         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4431         {
4432                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4433                 if (i == 4)
4434                         continue;
4435                 p = r_refdef.view.frustum + i;
4436                 switch(p->signbits)
4437                 {
4438                 default:
4439                 case 0:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 1:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 2:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 3:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 4:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 5:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 6:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 7:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 }
4472         }
4473         return false;
4474 }
4475
4476 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4477 {
4478         int i;
4479         const mplane_t *p;
4480         if (r_trippy.integer)
4481                 return false;
4482         for (i = 0;i < numplanes;i++)
4483         {
4484                 p = planes + i;
4485                 switch(p->signbits)
4486                 {
4487                 default:
4488                 case 0:
4489                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4490                                 return true;
4491                         break;
4492                 case 1:
4493                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 case 2:
4497                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4498                                 return true;
4499                         break;
4500                 case 3:
4501                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4502                                 return true;
4503                         break;
4504                 case 4:
4505                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4506                                 return true;
4507                         break;
4508                 case 5:
4509                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4510                                 return true;
4511                         break;
4512                 case 6:
4513                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4514                                 return true;
4515                         break;
4516                 case 7:
4517                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4518                                 return true;
4519                         break;
4520                 }
4521         }
4522         return false;
4523 }
4524
4525 //==================================================================================
4526
4527 // LordHavoc: this stores temporary data used within the same frame
4528
4529 typedef struct r_framedata_mem_s
4530 {
4531         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4532         size_t size; // how much usable space
4533         size_t current; // how much space in use
4534         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4535         size_t wantedsize; // how much space was allocated
4536         unsigned char *data; // start of real data (16byte aligned)
4537 }
4538 r_framedata_mem_t;
4539
4540 static r_framedata_mem_t *r_framedata_mem;
4541
4542 void R_FrameData_Reset(void)
4543 {
4544         while (r_framedata_mem)
4545         {
4546                 r_framedata_mem_t *next = r_framedata_mem->purge;
4547                 Mem_Free(r_framedata_mem);
4548                 r_framedata_mem = next;
4549         }
4550 }
4551
4552 void R_FrameData_Resize(void)
4553 {
4554         size_t wantedsize;
4555         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4556         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4557         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4558         {
4559                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4560                 newmem->wantedsize = wantedsize;
4561                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4562                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4563                 newmem->current = 0;
4564                 newmem->mark = 0;
4565                 newmem->purge = r_framedata_mem;
4566                 r_framedata_mem = newmem;
4567         }
4568 }
4569
4570 void R_FrameData_NewFrame(void)
4571 {
4572         R_FrameData_Resize();
4573         if (!r_framedata_mem)
4574                 return;
4575         // if we ran out of space on the last frame, free the old memory now
4576         while (r_framedata_mem->purge)
4577         {
4578                 // repeatedly remove the second item in the list, leaving only head
4579                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4580                 Mem_Free(r_framedata_mem->purge);
4581                 r_framedata_mem->purge = next;
4582         }
4583         // reset the current mem pointer
4584         r_framedata_mem->current = 0;
4585         r_framedata_mem->mark = 0;
4586 }
4587
4588 void *R_FrameData_Alloc(size_t size)
4589 {
4590         void *data;
4591
4592         // align to 16 byte boundary - the data pointer is already aligned, so we
4593         // only need to ensure the size of every allocation is also aligned
4594         size = (size + 15) & ~15;
4595
4596         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4597         {
4598                 // emergency - we ran out of space, allocate more memory
4599                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4600                 R_FrameData_Resize();
4601         }
4602
4603         data = r_framedata_mem->data + r_framedata_mem->current;
4604         r_framedata_mem->current += size;
4605
4606         // count the usage for stats
4607         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4608         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4609
4610         return (void *)data;
4611 }
4612
4613 void *R_FrameData_Store(size_t size, void *data)
4614 {
4615         void *d = R_FrameData_Alloc(size);
4616         if (d && data)
4617                 memcpy(d, data, size);
4618         return d;
4619 }
4620
4621 void R_FrameData_SetMark(void)
4622 {
4623         if (!r_framedata_mem)
4624                 return;
4625         r_framedata_mem->mark = r_framedata_mem->current;
4626 }
4627
4628 void R_FrameData_ReturnToMark(void)
4629 {
4630         if (!r_framedata_mem)
4631                 return;
4632         r_framedata_mem->current = r_framedata_mem->mark;
4633 }
4634
4635 //==================================================================================
4636
4637 // LordHavoc: animcache originally written by Echon, rewritten since then
4638
4639 /**
4640  * Animation cache prevents re-generating mesh data for an animated model
4641  * multiple times in one frame for lighting, shadowing, reflections, etc.
4642  */
4643
4644 void R_AnimCache_Free(void)
4645 {
4646 }
4647
4648 void R_AnimCache_ClearCache(void)
4649 {
4650         int i;
4651         entity_render_t *ent;
4652
4653         for (i = 0;i < r_refdef.scene.numentities;i++)
4654         {
4655                 ent = r_refdef.scene.entities[i];
4656                 ent->animcache_vertex3f = NULL;
4657                 ent->animcache_normal3f = NULL;
4658                 ent->animcache_svector3f = NULL;
4659                 ent->animcache_tvector3f = NULL;
4660                 ent->animcache_vertexmesh = NULL;
4661                 ent->animcache_vertex3fbuffer = NULL;
4662                 ent->animcache_vertexmeshbuffer = NULL;
4663         }
4664 }
4665
4666 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4667 {
4668         int i;
4669
4670         // check if we need the meshbuffers
4671         if (!vid.useinterleavedarrays)
4672                 return;
4673
4674         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4675                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4676         // TODO: upload vertex3f buffer?
4677         if (ent->animcache_vertexmesh)
4678         {
4679                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4680                 for (i = 0;i < numvertices;i++)
4681                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4682                 if (ent->animcache_svector3f)
4683                         for (i = 0;i < numvertices;i++)
4684                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4685                 if (ent->animcache_tvector3f)
4686                         for (i = 0;i < numvertices;i++)
4687                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4688                 if (ent->animcache_normal3f)
4689                         for (i = 0;i < numvertices;i++)
4690                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4691                 // TODO: upload vertexmeshbuffer?
4692         }
4693 }
4694
4695 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4696 {
4697         dp_model_t *model = ent->model;
4698         int numvertices;
4699         // see if it's already cached this frame
4700         if (ent->animcache_vertex3f)
4701         {
4702                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4703                 if (wantnormals || wanttangents)
4704                 {
4705                         if (ent->animcache_normal3f)
4706                                 wantnormals = false;
4707                         if (ent->animcache_svector3f)
4708                                 wanttangents = false;
4709                         if (wantnormals || wanttangents)
4710                         {
4711                                 numvertices = model->surfmesh.num_vertices;
4712                                 if (wantnormals)
4713                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                                 if (wanttangents)
4715                                 {
4716                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4717                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4718                                 }
4719                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4720                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4721                         }
4722                 }
4723         }
4724         else
4725         {
4726                 // see if this ent is worth caching
4727                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4728                         return false;
4729                 // get some memory for this entity and generate mesh data
4730                 numvertices = model->surfmesh.num_vertices;
4731                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4732                 if (wantnormals)
4733                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4734                 if (wanttangents)
4735                 {
4736                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4737                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4738                 }
4739                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4740                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4741         }
4742         return true;
4743 }
4744
4745 void R_AnimCache_CacheVisibleEntities(void)
4746 {
4747         int i;
4748         qboolean wantnormals = true;
4749         qboolean wanttangents = !r_showsurfaces.integer;
4750
4751         switch(vid.renderpath)
4752         {
4753         case RENDERPATH_GL20:
4754         case RENDERPATH_D3D9:
4755         case RENDERPATH_D3D10:
4756         case RENDERPATH_D3D11:
4757         case RENDERPATH_GLES2:
4758                 break;
4759         case RENDERPATH_GL11:
4760         case RENDERPATH_GL13:
4761         case RENDERPATH_GLES1:
4762                 wanttangents = false;
4763                 break;
4764         case RENDERPATH_SOFT:
4765                 break;
4766         }
4767
4768         if (r_shownormals.integer)
4769                 wanttangents = wantnormals = true;
4770
4771         // TODO: thread this
4772         // NOTE: R_PrepareRTLights() also caches entities
4773
4774         for (i = 0;i < r_refdef.scene.numentities;i++)
4775                 if (r_refdef.viewcache.entityvisible[i])
4776                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4777 }
4778
4779 //==================================================================================
4780
4781 extern cvar_t r_overheadsprites_pushback;
4782
4783 static void R_View_UpdateEntityLighting (void)
4784 {
4785         int i;
4786         entity_render_t *ent;
4787         vec3_t tempdiffusenormal, avg;
4788         vec_t f, fa, fd, fdd;
4789         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4790
4791         for (i = 0;i < r_refdef.scene.numentities;i++)
4792         {
4793                 ent = r_refdef.scene.entities[i];
4794
4795                 // skip unseen models
4796                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4797                         continue;
4798
4799                 // skip bsp models
4800                 if (ent->model && ent->model->brush.num_leafs)
4801                 {
4802                         // TODO: use modellight for r_ambient settings on world?
4803                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4804                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4805                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4806                         continue;
4807                 }
4808
4809                 // fetch the lighting from the worldmodel data
4810                 VectorClear(ent->modellight_ambient);
4811                 VectorClear(ent->modellight_diffuse);
4812                 VectorClear(tempdiffusenormal);
4813                 if (ent->flags & RENDER_LIGHT)
4814                 {
4815                         vec3_t org;
4816                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4817
4818                         // complete lightning for lit sprites
4819                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4820                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4821                         {
4822                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4823                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4824                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4825                         }
4826                         else
4827                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4828
4829                         if(ent->flags & RENDER_EQUALIZE)
4830                         {
4831                                 // first fix up ambient lighting...
4832                                 if(r_equalize_entities_minambient.value > 0)
4833                                 {
4834                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4835                                         if(fd > 0)
4836                                         {
4837                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4838                                                 if(fa < r_equalize_entities_minambient.value * fd)
4839                                                 {
4840                                                         // solve:
4841                                                         //   fa'/fd' = minambient
4842                                                         //   fa'+0.25*fd' = fa+0.25*fd
4843                                                         //   ...
4844                                                         //   fa' = fd' * minambient
4845                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4846                                                         //   ...
4847                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4848                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4849                                                         //   ...
4850                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4851                                                         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
4852                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4853                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4854                                                 }
4855                                         }
4856                                 }
4857
4858                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4859                                 {
4860                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4861                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4862                                         f = fa + 0.25 * fd;
4863                                         if(f > 0)
4864                                         {
4865                                                 // adjust brightness and saturation to target
4866                                                 avg[0] = avg[1] = avg[2] = fa / f;
4867                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4868                                                 avg[0] = avg[1] = avg[2] = fd / f;
4869                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4870                                         }
4871                                 }
4872                         }
4873                 }
4874                 else // highly rare
4875                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4876
4877                 // move the light direction into modelspace coordinates for lighting code
4878                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4879                 if(VectorLength2(ent->modellight_lightdir) == 0)
4880                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4881                 VectorNormalize(ent->modellight_lightdir);
4882         }
4883 }
4884
4885 #define MAX_LINEOFSIGHTTRACES 64
4886
4887 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4888 {
4889         int i;
4890         vec3_t boxmins, boxmaxs;
4891         vec3_t start;
4892         vec3_t end;
4893         dp_model_t *model = r_refdef.scene.worldmodel;
4894
4895         if (!model || !model->brush.TraceLineOfSight)
4896                 return true;
4897
4898         // expand the box a little
4899         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4900         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4901         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4902         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4903         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4904         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4905
4906         // return true if eye is inside enlarged box
4907         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4908                 return true;
4909
4910         // try center
4911         VectorCopy(eye, start);
4912         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4913         if (model->brush.TraceLineOfSight(model, start, end))
4914                 return true;
4915
4916         // try various random positions
4917         for (i = 0;i < numsamples;i++)
4918         {
4919                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4920                 if (model->brush.TraceLineOfSight(model, start, end))
4921                         return true;
4922         }
4923
4924         return false;
4925 }
4926
4927
4928 static void R_View_UpdateEntityVisible (void)
4929 {
4930         int i;
4931         int renderimask;
4932         int samples;
4933         entity_render_t *ent;
4934
4935         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4936                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4937                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4938                 :                                                          RENDER_EXTERIORMODEL;
4939         if (!r_drawviewmodel.integer)
4940                 renderimask |= RENDER_VIEWMODEL;
4941         if (!r_drawexteriormodel.integer)
4942                 renderimask |= RENDER_EXTERIORMODEL;
4943         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4944         {
4945                 // worldmodel can check visibility
4946                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4947                 for (i = 0;i < r_refdef.scene.numentities;i++)
4948                 {
4949                         ent = r_refdef.scene.entities[i];
4950                         if (!(ent->flags & renderimask))
4951                         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)))
4952                         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))
4953                                 r_refdef.viewcache.entityvisible[i] = true;
4954                 }
4955         }
4956         else
4957         {
4958                 // no worldmodel or it can't check visibility
4959                 for (i = 0;i < r_refdef.scene.numentities;i++)
4960                 {
4961                         ent = r_refdef.scene.entities[i];
4962                         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));
4963                 }
4964         }
4965         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4966                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4967         {
4968                 for (i = 0;i < r_refdef.scene.numentities;i++)
4969                 {
4970                         if (!r_refdef.viewcache.entityvisible[i])
4971                                 continue;
4972                         ent = r_refdef.scene.entities[i];
4973                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4974                         {
4975                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4976                                 if (samples < 0)
4977                                         continue; // temp entities do pvs only
4978                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4979                                         ent->last_trace_visibility = realtime;
4980                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4981                                         r_refdef.viewcache.entityvisible[i] = 0;
4982                         }
4983                 }
4984         }
4985 }
4986
4987 /// only used if skyrendermasked, and normally returns false
4988 int R_DrawBrushModelsSky (void)
4989 {
4990         int i, sky;
4991         entity_render_t *ent;
4992
4993         sky = false;
4994         for (i = 0;i < r_refdef.scene.numentities;i++)
4995         {
4996                 if (!r_refdef.viewcache.entityvisible[i])
4997                         continue;
4998                 ent = r_refdef.scene.entities[i];
4999                 if (!ent->model || !ent->model->DrawSky)
5000                         continue;
5001                 ent->model->DrawSky(ent);
5002                 sky = true;
5003         }
5004         return sky;
5005 }
5006
5007 static void R_DrawNoModel(entity_render_t *ent);
5008 static void R_DrawModels(void)
5009 {
5010         int i;
5011         entity_render_t *ent;
5012
5013         for (i = 0;i < r_refdef.scene.numentities;i++)
5014         {
5015                 if (!r_refdef.viewcache.entityvisible[i])
5016                         continue;
5017                 ent = r_refdef.scene.entities[i];
5018                 r_refdef.stats.entities++;
5019                 /*
5020                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5021                 {
5022                         vec3_t f, l, u, o;
5023                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5024                         Con_Printf("R_DrawModels\n");
5025                         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]);
5026                         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);
5027                         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);
5028                 }
5029                 */
5030                 if (ent->model && ent->model->Draw != NULL)
5031                         ent->model->Draw(ent);
5032                 else
5033                         R_DrawNoModel(ent);
5034         }
5035 }
5036
5037 static void R_DrawModelsDepth(void)
5038 {
5039         int i;
5040         entity_render_t *ent;
5041
5042         for (i = 0;i < r_refdef.scene.numentities;i++)
5043         {
5044                 if (!r_refdef.viewcache.entityvisible[i])
5045                         continue;
5046                 ent = r_refdef.scene.entities[i];
5047                 if (ent->model && ent->model->DrawDepth != NULL)
5048                         ent->model->DrawDepth(ent);
5049         }
5050 }
5051
5052 static void R_DrawModelsDebug(void)
5053 {
5054         int i;
5055         entity_render_t *ent;
5056
5057         for (i = 0;i < r_refdef.scene.numentities;i++)
5058         {
5059                 if (!r_refdef.viewcache.entityvisible[i])
5060                         continue;
5061                 ent = r_refdef.scene.entities[i];
5062                 if (ent->model && ent->model->DrawDebug != NULL)
5063                         ent->model->DrawDebug(ent);
5064         }
5065 }
5066
5067 static void R_DrawModelsAddWaterPlanes(void)
5068 {
5069         int i;
5070         entity_render_t *ent;
5071
5072         for (i = 0;i < r_refdef.scene.numentities;i++)
5073         {
5074                 if (!r_refdef.viewcache.entityvisible[i])
5075                         continue;
5076                 ent = r_refdef.scene.entities[i];
5077                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5078                         ent->model->DrawAddWaterPlanes(ent);
5079         }
5080 }
5081
5082 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5083 {
5084         if (r_hdr_irisadaptation.integer)
5085         {
5086                 vec3_t ambient;
5087                 vec3_t diffuse;
5088                 vec3_t diffusenormal;
5089                 vec_t brightness;
5090                 vec_t goal;
5091                 vec_t current;
5092                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5093                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5094                 brightness = max(0.0000001f, brightness);
5095                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5096                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5097                 current = r_hdr_irisadaptation_value.value;
5098                 if (current < goal)
5099                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5100                 else if (current > goal)
5101                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5102                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5103                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5104         }
5105         else if (r_hdr_irisadaptation_value.value != 1.0f)
5106                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5107 }
5108
5109 static void R_View_SetFrustum(const int *scissor)
5110 {
5111         int i;
5112         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5113         vec3_t forward, left, up, origin, v;
5114
5115         if(scissor)
5116         {
5117                 // flipped x coordinates (because x points left here)
5118                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5119                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5120
5121                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5122                 switch(vid.renderpath)
5123                 {
5124                         case RENDERPATH_D3D9:
5125                         case RENDERPATH_D3D10:
5126                         case RENDERPATH_D3D11:
5127                                 // non-flipped y coordinates
5128                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5129                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5130                                 break;
5131                         case RENDERPATH_SOFT:
5132                         case RENDERPATH_GL11:
5133                         case RENDERPATH_GL13:
5134                         case RENDERPATH_GL20:
5135                         case RENDERPATH_GLES1:
5136                         case RENDERPATH_GLES2:
5137                                 // non-flipped y coordinates
5138                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5139                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5140                                 break;
5141                 }
5142         }
5143
5144         // we can't trust r_refdef.view.forward and friends in reflected scenes
5145         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5146
5147 #if 0
5148         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5149         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5150         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5151         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5152         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5153         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5154         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5155         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5156         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5157         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5158         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5159         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5160 #endif
5161
5162 #if 0
5163         zNear = r_refdef.nearclip;
5164         nudge = 1.0 - 1.0 / (1<<23);
5165         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5166         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5167         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5168         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5169         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5170         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5171         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5172         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5173 #endif
5174
5175
5176
5177 #if 0
5178         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5179         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5180         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5181         r_refdef.view.frustum[0].dist = m[15] - m[12];
5182
5183         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5184         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5185         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5186         r_refdef.view.frustum[1].dist = m[15] + m[12];
5187
5188         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5189         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5190         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5191         r_refdef.view.frustum[2].dist = m[15] - m[13];
5192
5193         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5194         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5195         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5196         r_refdef.view.frustum[3].dist = m[15] + m[13];
5197
5198         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5199         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5200         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5201         r_refdef.view.frustum[4].dist = m[15] - m[14];
5202
5203         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5204         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5205         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5206         r_refdef.view.frustum[5].dist = m[15] + m[14];
5207 #endif
5208
5209         if (r_refdef.view.useperspective)
5210         {
5211                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5212                 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]);
5213                 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]);
5214                 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]);
5215                 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]);
5216
5217                 // then the normals from the corners relative to origin
5218                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5219                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5220                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5221                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5222
5223                 // in a NORMAL view, forward cross left == up
5224                 // in a REFLECTED view, forward cross left == down
5225                 // so our cross products above need to be adjusted for a left handed coordinate system
5226                 CrossProduct(forward, left, v);
5227                 if(DotProduct(v, up) < 0)
5228                 {
5229                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5230                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5231                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5232                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5233                 }
5234
5235                 // Leaving those out was a mistake, those were in the old code, and they
5236                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5237                 // I couldn't reproduce it after adding those normalizations. --blub
5238                 VectorNormalize(r_refdef.view.frustum[0].normal);
5239                 VectorNormalize(r_refdef.view.frustum[1].normal);
5240                 VectorNormalize(r_refdef.view.frustum[2].normal);
5241                 VectorNormalize(r_refdef.view.frustum[3].normal);
5242
5243                 // make the corners absolute
5244                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5245                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5246                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5247                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5248
5249                 // one more normal
5250                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5251
5252                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5253                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5254                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5255                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5256                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5257         }
5258         else
5259         {
5260                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5261                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5262                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5263                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5264                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5265                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5266                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5267                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5268                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5269                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5270         }
5271         r_refdef.view.numfrustumplanes = 5;
5272
5273         if (r_refdef.view.useclipplane)
5274         {
5275                 r_refdef.view.numfrustumplanes = 6;
5276                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5277         }
5278
5279         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5280                 PlaneClassify(r_refdef.view.frustum + i);
5281
5282         // LordHavoc: note to all quake engine coders, Quake had a special case
5283         // for 90 degrees which assumed a square view (wrong), so I removed it,
5284         // Quake2 has it disabled as well.
5285
5286         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5287         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5288         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5289         //PlaneClassify(&frustum[0]);
5290
5291         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5292         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5293         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5294         //PlaneClassify(&frustum[1]);
5295
5296         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5297         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5298         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5299         //PlaneClassify(&frustum[2]);
5300
5301         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5302         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5303         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5304         //PlaneClassify(&frustum[3]);
5305
5306         // nearclip plane
5307         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5308         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5309         //PlaneClassify(&frustum[4]);
5310 }
5311
5312 void R_View_UpdateWithScissor(const int *myscissor)
5313 {
5314         R_Main_ResizeViewCache();
5315         R_View_SetFrustum(myscissor);
5316         R_View_WorldVisibility(r_refdef.view.useclipplane);
5317         R_View_UpdateEntityVisible();
5318         R_View_UpdateEntityLighting();
5319 }
5320
5321 void R_View_Update(void)
5322 {
5323         R_Main_ResizeViewCache();
5324         R_View_SetFrustum(NULL);
5325         R_View_WorldVisibility(r_refdef.view.useclipplane);
5326         R_View_UpdateEntityVisible();
5327         R_View_UpdateEntityLighting();
5328 }
5329
5330 float viewscalefpsadjusted = 1.0f;
5331
5332 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5333 {
5334         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5335         scale = bound(0.03125f, scale, 1.0f);
5336         *outwidth = (int)ceil(width * scale);
5337         *outheight = (int)ceil(height * scale);
5338 }
5339
5340 void R_Mesh_SetMainRenderTargets(void)
5341 {
5342         if (r_bloomstate.fbo_framebuffer)
5343                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5344         else
5345                 R_Mesh_ResetRenderTargets();
5346 }
5347
5348 void R_SetupView(qboolean allowwaterclippingplane)
5349 {
5350         const float *customclipplane = NULL;
5351         float plane[4];
5352         int scaledwidth, scaledheight;
5353         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5354         {
5355                 // LordHavoc: couldn't figure out how to make this approach the
5356                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5357                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5358                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5359                         dist = r_refdef.view.clipplane.dist;
5360                 plane[0] = r_refdef.view.clipplane.normal[0];
5361                 plane[1] = r_refdef.view.clipplane.normal[1];
5362                 plane[2] = r_refdef.view.clipplane.normal[2];
5363                 plane[3] = -dist;
5364                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5365         }
5366
5367         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5368         if (!r_refdef.view.useperspective)
5369                 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);
5370         else if (vid.stencil && r_useinfinitefarclip.integer)
5371                 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);
5372         else
5373                 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);
5374         R_Mesh_SetMainRenderTargets();
5375         R_SetViewport(&r_refdef.view.viewport);
5376         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5377         {
5378                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5379                 float screenplane[4];
5380                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5381                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5382                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5383                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5384                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5385         }
5386 }
5387
5388 void R_EntityMatrix(const matrix4x4_t *matrix)
5389 {
5390         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5391         {
5392                 gl_modelmatrixchanged = false;
5393                 gl_modelmatrix = *matrix;
5394                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5395                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5396                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5397                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5398                 CHECKGLERROR
5399                 switch(vid.renderpath)
5400                 {
5401                 case RENDERPATH_D3D9:
5402 #ifdef SUPPORTD3D
5403                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5404                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5405 #endif
5406                         break;
5407                 case RENDERPATH_D3D10:
5408                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5409                         break;
5410                 case RENDERPATH_D3D11:
5411                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5412                         break;
5413                 case RENDERPATH_GL11:
5414                 case RENDERPATH_GL13:
5415                 case RENDERPATH_GLES1:
5416                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5417                         break;
5418                 case RENDERPATH_SOFT:
5419                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5420                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5421                         break;
5422                 case RENDERPATH_GL20:
5423                 case RENDERPATH_GLES2:
5424                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5425                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5426                         break;
5427                 }
5428         }
5429 }
5430
5431 void R_ResetViewRendering2D(void)
5432 {
5433         r_viewport_t viewport;
5434         DrawQ_Finish();
5435
5436         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5437         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);
5438         R_Mesh_ResetRenderTargets();
5439         R_SetViewport(&viewport);
5440         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5441         GL_Color(1, 1, 1, 1);
5442         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5443         GL_BlendFunc(GL_ONE, GL_ZERO);
5444         GL_ScissorTest(false);
5445         GL_DepthMask(false);
5446         GL_DepthRange(0, 1);
5447         GL_DepthTest(false);
5448         GL_DepthFunc(GL_LEQUAL);
5449         R_EntityMatrix(&identitymatrix);
5450         R_Mesh_ResetTextureState();
5451         GL_PolygonOffset(0, 0);
5452         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5453         switch(vid.renderpath)
5454         {
5455         case RENDERPATH_GL11:
5456         case RENDERPATH_GL13:
5457         case RENDERPATH_GL20:
5458         case RENDERPATH_GLES1:
5459         case RENDERPATH_GLES2:
5460                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5461                 break;
5462         case RENDERPATH_D3D9:
5463         case RENDERPATH_D3D10:
5464         case RENDERPATH_D3D11:
5465         case RENDERPATH_SOFT:
5466                 break;
5467         }
5468         GL_CullFace(GL_NONE);
5469 }
5470
5471 void R_ResetViewRendering3D(void)
5472 {
5473         DrawQ_Finish();
5474
5475         R_SetupView(true);
5476         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5477         GL_Color(1, 1, 1, 1);
5478         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5479         GL_BlendFunc(GL_ONE, GL_ZERO);
5480         GL_ScissorTest(true);
5481         GL_DepthMask(true);
5482         GL_DepthRange(0, 1);
5483         GL_DepthTest(true);
5484         GL_DepthFunc(GL_LEQUAL);
5485         R_EntityMatrix(&identitymatrix);
5486         R_Mesh_ResetTextureState();
5487         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5488         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5489         switch(vid.renderpath)
5490         {
5491         case RENDERPATH_GL11:
5492         case RENDERPATH_GL13:
5493         case RENDERPATH_GL20:
5494         case RENDERPATH_GLES1:
5495         case RENDERPATH_GLES2:
5496                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5497                 break;
5498         case RENDERPATH_D3D9:
5499         case RENDERPATH_D3D10:
5500         case RENDERPATH_D3D11:
5501         case RENDERPATH_SOFT:
5502                 break;
5503         }
5504         GL_CullFace(r_refdef.view.cullface_back);
5505 }
5506
5507 /*
5508 ================
5509 R_RenderView_UpdateViewVectors
5510 ================
5511 */
5512 static void R_RenderView_UpdateViewVectors(void)
5513 {
5514         // break apart the view matrix into vectors for various purposes
5515         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5516         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5517         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5518         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5519         // make an inverted copy of the view matrix for tracking sprites
5520         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5521 }
5522
5523 void R_RenderScene(void);
5524 void R_RenderWaterPlanes(void);
5525
5526 static void R_Water_StartFrame(void)
5527 {
5528         int i;
5529         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5530         r_waterstate_waterplane_t *p;
5531
5532         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5533                 return;
5534
5535         switch(vid.renderpath)
5536         {
5537         case RENDERPATH_GL20:
5538         case RENDERPATH_D3D9:
5539         case RENDERPATH_D3D10:
5540         case RENDERPATH_D3D11:
5541         case RENDERPATH_SOFT:
5542         case RENDERPATH_GLES2:
5543                 break;
5544         case RENDERPATH_GL11:
5545         case RENDERPATH_GL13:
5546         case RENDERPATH_GLES1:
5547                 return;
5548         }
5549
5550         // set waterwidth and waterheight to the water resolution that will be
5551         // used (often less than the screen resolution for faster rendering)
5552         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5553
5554         // calculate desired texture sizes
5555         // can't use water if the card does not support the texture size
5556         if (!r_water.integer || r_showsurfaces.integer)
5557                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5558         else if (vid.support.arb_texture_non_power_of_two)
5559         {
5560                 texturewidth = waterwidth;
5561                 textureheight = waterheight;
5562                 camerawidth = waterwidth;
5563                 cameraheight = waterheight;
5564         }
5565         else
5566         {
5567                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5568                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5569                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5570                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5571         }
5572
5573         // allocate textures as needed
5574         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5575         {
5576                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5577                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5578                 {
5579                         if (p->texture_refraction)
5580                                 R_FreeTexture(p->texture_refraction);
5581                         p->texture_refraction = NULL;
5582                         if (p->texture_reflection)
5583                                 R_FreeTexture(p->texture_reflection);
5584                         p->texture_reflection = NULL;
5585                         if (p->texture_camera)
5586                                 R_FreeTexture(p->texture_camera);
5587                         p->texture_camera = NULL;
5588                 }
5589                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5590                 r_waterstate.texturewidth = texturewidth;
5591                 r_waterstate.textureheight = textureheight;
5592                 r_waterstate.camerawidth = camerawidth;
5593                 r_waterstate.cameraheight = cameraheight;
5594         }
5595
5596         if (r_waterstate.texturewidth)
5597         {
5598                 int scaledwidth, scaledheight;
5599
5600                 r_waterstate.enabled = true;
5601
5602                 // when doing a reduced render (HDR) we want to use a smaller area
5603                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5604                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5605                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5606
5607                 // set up variables that will be used in shader setup
5608                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5609                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5610                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5611                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5612         }
5613
5614         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5615         r_waterstate.numwaterplanes = 0;
5616 }
5617
5618 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5619 {
5620         int triangleindex, planeindex;
5621         const int *e;
5622         vec3_t vert[3];
5623         vec3_t normal;
5624         vec3_t center;
5625         mplane_t plane;
5626         r_waterstate_waterplane_t *p;
5627         texture_t *t = R_GetCurrentTexture(surface->texture);
5628
5629         // just use the first triangle with a valid normal for any decisions
5630         VectorClear(normal);
5631         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5632         {
5633                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5635                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5636                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5637                 if (VectorLength2(normal) >= 0.001)
5638                         break;
5639         }
5640
5641         VectorCopy(normal, plane.normal);
5642         VectorNormalize(plane.normal);
5643         plane.dist = DotProduct(vert[0], plane.normal);
5644         PlaneClassify(&plane);
5645         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5646         {
5647                 // skip backfaces (except if nocullface is set)
5648                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5649                         return;
5650                 VectorNegate(plane.normal, plane.normal);
5651                 plane.dist *= -1;
5652                 PlaneClassify(&plane);
5653         }
5654
5655
5656         // find a matching plane if there is one
5657         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5658                 if(p->camera_entity == t->camera_entity)
5659                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5660                                 break;
5661         if (planeindex >= r_waterstate.maxwaterplanes)
5662                 return; // nothing we can do, out of planes
5663
5664         // if this triangle does not fit any known plane rendered this frame, add one
5665         if (planeindex >= r_waterstate.numwaterplanes)
5666         {
5667                 // store the new plane
5668                 r_waterstate.numwaterplanes++;
5669                 p->plane = plane;
5670                 // clear materialflags and pvs
5671                 p->materialflags = 0;
5672                 p->pvsvalid = false;
5673                 p->camera_entity = t->camera_entity;
5674                 VectorCopy(surface->mins, p->mins);
5675                 VectorCopy(surface->maxs, p->maxs);
5676         }
5677         else
5678         {
5679                 // merge mins/maxs
5680                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5681                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5682                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5683                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5684                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5685                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5686         }
5687         // merge this surface's materialflags into the waterplane
5688         p->materialflags |= t->currentmaterialflags;
5689         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5690         {
5691                 // merge this surface's PVS into the waterplane
5692                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5694                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5695                 {
5696                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5697                         p->pvsvalid = true;
5698                 }
5699         }
5700 }
5701
5702 extern cvar_t r_drawparticles;
5703 extern cvar_t r_drawdecals;
5704
5705 static void R_Water_ProcessPlanes(void)
5706 {
5707         int myscissor[4];
5708         r_refdef_view_t originalview;
5709         r_refdef_view_t myview;
5710         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;
5711         r_waterstate_waterplane_t *p;
5712         vec3_t visorigin;
5713
5714         originalview = r_refdef.view;
5715
5716         // lowquality hack, temporarily shut down some cvars and restore afterwards
5717         qualityreduction = r_water_lowquality.integer;
5718         if (qualityreduction > 0)
5719         {
5720                 if (qualityreduction >= 1)
5721                 {
5722                         old_r_shadows = r_shadows.integer;
5723                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5724                         old_r_dlight = r_shadow_realtime_dlight.integer;
5725                         Cvar_SetValueQuick(&r_shadows, 0);
5726                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5727                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5728                 }
5729                 if (qualityreduction >= 2)
5730                 {
5731                         old_r_dynamic = r_dynamic.integer;
5732                         old_r_particles = r_drawparticles.integer;
5733                         old_r_decals = r_drawdecals.integer;
5734                         Cvar_SetValueQuick(&r_dynamic, 0);
5735                         Cvar_SetValueQuick(&r_drawparticles, 0);
5736                         Cvar_SetValueQuick(&r_drawdecals, 0);
5737                 }
5738         }
5739
5740         // make sure enough textures are allocated
5741         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5742         {
5743                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5744                 {
5745                         if (!p->texture_refraction)
5746                                 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);
5747                         if (!p->texture_refraction)
5748                                 goto error;
5749                 }
5750                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5751                 {
5752                         if (!p->texture_camera)
5753                                 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);
5754                         if (!p->texture_camera)
5755                                 goto error;
5756                 }
5757
5758                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5759                 {
5760                         if (!p->texture_reflection)
5761                                 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);
5762                         if (!p->texture_reflection)
5763                                 goto error;
5764                 }
5765         }
5766
5767         // render views
5768         r_refdef.view = originalview;
5769         r_refdef.view.showdebug = false;
5770         r_refdef.view.width = r_waterstate.waterwidth;
5771         r_refdef.view.height = r_waterstate.waterheight;
5772         r_refdef.view.useclipplane = true;
5773         myview = r_refdef.view;
5774         r_waterstate.renderingscene = true;
5775         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5776         {
5777                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5778                 {
5779                         r_refdef.view = myview;
5780                         if(r_water_scissormode.integer)
5781                         {
5782                                 R_SetupView(true);
5783                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5784                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5785                         }
5786
5787                         // render reflected scene and copy into texture
5788                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5789                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5790                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5791                         r_refdef.view.clipplane = p->plane;
5792                         // reverse the cullface settings for this render
5793                         r_refdef.view.cullface_front = GL_FRONT;
5794                         r_refdef.view.cullface_back = GL_BACK;
5795                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5796                         {
5797                                 r_refdef.view.usecustompvs = true;
5798                                 if (p->pvsvalid)
5799                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5800                                 else
5801                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5802                         }
5803
5804                         R_ResetViewRendering3D();
5805                         R_ClearScreen(r_refdef.fogenabled);
5806                         if(r_water_scissormode.integer & 2)
5807                                 R_View_UpdateWithScissor(myscissor);
5808                         else
5809                                 R_View_Update();
5810                         if(r_water_scissormode.integer & 1)
5811                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5812                         R_RenderScene();
5813
5814                         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);
5815                 }
5816
5817                 // render the normal view scene and copy into texture
5818                 // (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)
5819                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5820                 {
5821                         r_refdef.view = myview;
5822                         if(r_water_scissormode.integer)
5823                         {
5824                                 R_SetupView(true);
5825                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5826                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5827                         }
5828
5829                         r_waterstate.renderingrefraction = true;
5830
5831                         r_refdef.view.clipplane = p->plane;
5832                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5833                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5834
5835                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5836                         {
5837                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5838                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5839                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5840                                 R_RenderView_UpdateViewVectors();
5841                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5842                                 {
5843                                         r_refdef.view.usecustompvs = true;
5844                                         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);
5845                                 }
5846                         }
5847
5848                         PlaneClassify(&r_refdef.view.clipplane);
5849
5850                         R_ResetViewRendering3D();
5851                         R_ClearScreen(r_refdef.fogenabled);
5852                         if(r_water_scissormode.integer & 2)
5853                                 R_View_UpdateWithScissor(myscissor);
5854                         else
5855                                 R_View_Update();
5856                         if(r_water_scissormode.integer & 1)
5857                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5858                         R_RenderScene();
5859
5860                         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);
5861                         r_waterstate.renderingrefraction = false;
5862                 }
5863                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5864                 {
5865                         r_refdef.view = myview;
5866
5867                         r_refdef.view.clipplane = p->plane;
5868                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5869                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5870
5871                         r_refdef.view.width = r_waterstate.camerawidth;
5872                         r_refdef.view.height = r_waterstate.cameraheight;
5873                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5874                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5875
5876                         if(p->camera_entity)
5877                         {
5878                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5879                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5880                         }
5881
5882                         // note: all of the view is used for displaying... so
5883                         // there is no use in scissoring
5884
5885                         // reverse the cullface settings for this render
5886                         r_refdef.view.cullface_front = GL_FRONT;
5887                         r_refdef.view.cullface_back = GL_BACK;
5888                         // also reverse the view matrix
5889                         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
5890                         R_RenderView_UpdateViewVectors();
5891                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5892                         {
5893                                 r_refdef.view.usecustompvs = true;
5894                                 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);
5895                         }
5896                         
5897                         // camera needs no clipplane
5898                         r_refdef.view.useclipplane = false;
5899
5900                         PlaneClassify(&r_refdef.view.clipplane);
5901
5902                         R_ResetViewRendering3D();
5903                         R_ClearScreen(r_refdef.fogenabled);
5904                         R_View_Update();
5905                         R_RenderScene();
5906
5907                         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);
5908                         r_waterstate.renderingrefraction = false;
5909                 }
5910
5911         }
5912         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5913         r_waterstate.renderingscene = false;
5914         r_refdef.view = originalview;
5915         R_ResetViewRendering3D();
5916         R_ClearScreen(r_refdef.fogenabled);
5917         R_View_Update();
5918         goto finish;
5919 error:
5920         r_refdef.view = originalview;
5921         r_waterstate.renderingscene = false;
5922         Cvar_SetValueQuick(&r_water, 0);
5923         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5924 finish:
5925         // lowquality hack, restore cvars
5926         if (qualityreduction > 0)
5927         {
5928                 if (qualityreduction >= 1)
5929                 {
5930                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5931                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5932                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5933                 }
5934                 if (qualityreduction >= 2)
5935                 {
5936                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5937                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5938                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5939                 }
5940         }
5941 }
5942
5943 void R_Bloom_StartFrame(void)
5944 {
5945         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5946         int viewwidth, viewheight;
5947         textype_t textype;
5948
5949         if (r_viewscale_fpsscaling.integer)
5950         {
5951                 double actualframetime;
5952                 double targetframetime;
5953                 double adjust;
5954                 actualframetime = r_refdef.lastdrawscreentime;
5955                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5956                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5957                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5958                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5959                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5960                 viewscalefpsadjusted += adjust;
5961                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5962         }
5963         else
5964                 viewscalefpsadjusted = 1.0f;
5965
5966         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5967
5968         switch(vid.renderpath)
5969         {
5970         case RENDERPATH_GL20:
5971         case RENDERPATH_D3D9:
5972         case RENDERPATH_D3D10:
5973         case RENDERPATH_D3D11:
5974         case RENDERPATH_SOFT:
5975         case RENDERPATH_GLES2:
5976                 break;
5977         case RENDERPATH_GL11:
5978         case RENDERPATH_GL13:
5979         case RENDERPATH_GLES1:
5980                 return;
5981         }
5982
5983         // set bloomwidth and bloomheight to the bloom resolution that will be
5984         // used (often less than the screen resolution for faster rendering)
5985         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5986         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5987         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5988         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5989         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5990
5991         // calculate desired texture sizes
5992         if (vid.support.arb_texture_non_power_of_two)
5993         {
5994                 screentexturewidth = vid.width;
5995                 screentextureheight = vid.height;
5996                 bloomtexturewidth = r_bloomstate.bloomwidth;
5997                 bloomtextureheight = r_bloomstate.bloomheight;
5998         }
5999         else
6000         {
6001                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6002                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6003                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6004                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6005         }
6006
6007         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))
6008         {
6009                 Cvar_SetValueQuick(&r_hdr, 0);
6010                 Cvar_SetValueQuick(&r_bloom, 0);
6011                 Cvar_SetValueQuick(&r_motionblur, 0);
6012                 Cvar_SetValueQuick(&r_damageblur, 0);
6013         }
6014
6015         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)
6016                 screentexturewidth = screentextureheight = 0;
6017         if (!r_hdr.integer && !r_bloom.integer)
6018                 bloomtexturewidth = bloomtextureheight = 0;
6019
6020         textype = TEXTYPE_COLORBUFFER;
6021         switch (vid.renderpath)
6022         {
6023         case RENDERPATH_GL20:
6024         case RENDERPATH_GLES2:
6025                 if (vid.support.ext_framebuffer_object)
6026                 {
6027                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6028                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6029                 }
6030                 break;
6031         case RENDERPATH_GL11:
6032         case RENDERPATH_GL13:
6033         case RENDERPATH_GLES1:
6034         case RENDERPATH_D3D9:
6035         case RENDERPATH_D3D10:
6036         case RENDERPATH_D3D11:
6037         case RENDERPATH_SOFT:
6038                 break;
6039         }
6040
6041         // allocate textures as needed
6042         if (r_bloomstate.screentexturewidth != screentexturewidth
6043          || r_bloomstate.screentextureheight != screentextureheight
6044          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6045          || r_bloomstate.bloomtextureheight != bloomtextureheight
6046          || r_bloomstate.texturetype != textype
6047          || r_bloomstate.viewfbo != r_viewfbo.integer)
6048         {
6049                 if (r_bloomstate.texture_bloom)
6050                         R_FreeTexture(r_bloomstate.texture_bloom);
6051                 r_bloomstate.texture_bloom = NULL;
6052                 if (r_bloomstate.texture_screen)
6053                         R_FreeTexture(r_bloomstate.texture_screen);
6054                 r_bloomstate.texture_screen = NULL;
6055                 if (r_bloomstate.fbo_framebuffer)
6056                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6057                 r_bloomstate.fbo_framebuffer = 0;
6058                 if (r_bloomstate.texture_framebuffercolor)
6059                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6060                 r_bloomstate.texture_framebuffercolor = NULL;
6061                 if (r_bloomstate.texture_framebufferdepth)
6062                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6063                 r_bloomstate.texture_framebufferdepth = NULL;
6064                 r_bloomstate.screentexturewidth = screentexturewidth;
6065                 r_bloomstate.screentextureheight = screentextureheight;
6066                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6067                         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);
6068                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6069                 {
6070                         // FIXME: choose depth bits based on a cvar
6071                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6072                         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);
6073                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6074                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6075 #ifndef USE_GLES2
6076                         // render depth into one texture and normalmap into the other
6077                         if (qglDrawBuffer)
6078                         {
6079                                 int status;
6080                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6081                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6082                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6083                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6084                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6085                         }
6086 #endif
6087                 }
6088                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6089                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6090                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6091                         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);
6092                 r_bloomstate.viewfbo = r_viewfbo.integer;
6093                 r_bloomstate.texturetype = textype;
6094         }
6095
6096         // when doing a reduced render (HDR) we want to use a smaller area
6097         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6098         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6099         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6100         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6101         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6102
6103         // set up a texcoord array for the full resolution screen image
6104         // (we have to keep this around to copy back during final render)
6105         r_bloomstate.screentexcoord2f[0] = 0;
6106         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6107         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6108         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6109         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6110         r_bloomstate.screentexcoord2f[5] = 0;
6111         r_bloomstate.screentexcoord2f[6] = 0;
6112         r_bloomstate.screentexcoord2f[7] = 0;
6113
6114         // set up a texcoord array for the reduced resolution bloom image
6115         // (which will be additive blended over the screen image)
6116         r_bloomstate.bloomtexcoord2f[0] = 0;
6117         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6118         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6119         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6120         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6121         r_bloomstate.bloomtexcoord2f[5] = 0;
6122         r_bloomstate.bloomtexcoord2f[6] = 0;
6123         r_bloomstate.bloomtexcoord2f[7] = 0;
6124
6125         switch(vid.renderpath)
6126         {
6127         case RENDERPATH_GL11:
6128         case RENDERPATH_GL13:
6129         case RENDERPATH_GL20:
6130         case RENDERPATH_SOFT:
6131         case RENDERPATH_GLES1:
6132         case RENDERPATH_GLES2:
6133                 break;
6134         case RENDERPATH_D3D9:
6135         case RENDERPATH_D3D10:
6136         case RENDERPATH_D3D11:
6137                 {
6138                         int i;
6139                         for (i = 0;i < 4;i++)
6140                         {
6141                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6142                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6143                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6144                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6145                         }
6146                 }
6147                 break;
6148         }
6149
6150         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6151         {
6152                 r_bloomstate.enabled = true;
6153                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6154         }
6155
6156         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);
6157
6158         if (r_bloomstate.fbo_framebuffer)
6159                 r_refdef.view.clear = true;
6160 }
6161
6162 void R_Bloom_CopyBloomTexture(float colorscale)
6163 {
6164         r_refdef.stats.bloom++;
6165
6166         // scale down screen texture to the bloom texture size
6167         CHECKGLERROR
6168         R_Mesh_SetMainRenderTargets();
6169         R_SetViewport(&r_bloomstate.viewport);
6170         GL_BlendFunc(GL_ONE, GL_ZERO);
6171         GL_Color(colorscale, colorscale, colorscale, 1);
6172         // 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...
6173         switch(vid.renderpath)
6174         {
6175         case RENDERPATH_GL11:
6176         case RENDERPATH_GL13:
6177         case RENDERPATH_GL20:
6178         case RENDERPATH_GLES1:
6179         case RENDERPATH_GLES2:
6180         case RENDERPATH_SOFT:
6181                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6182                 break;
6183         case RENDERPATH_D3D9:
6184         case RENDERPATH_D3D10:
6185         case RENDERPATH_D3D11:
6186                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6187                 break;
6188         }
6189         // TODO: do boxfilter scale-down in shader?
6190         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6191         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6192         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6193
6194         // we now have a bloom image in the framebuffer
6195         // copy it into the bloom image texture for later processing
6196         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);
6197         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6198 }
6199
6200 void R_Bloom_CopyHDRTexture(void)
6201 {
6202         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);
6203         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6204 }
6205
6206 void R_Bloom_MakeTexture(void)
6207 {
6208         int x, range, dir;
6209         float xoffset, yoffset, r, brighten;
6210
6211         r_refdef.stats.bloom++;
6212
6213         R_ResetViewRendering2D();
6214
6215         // we have a bloom image in the framebuffer
6216         CHECKGLERROR
6217         R_SetViewport(&r_bloomstate.viewport);
6218
6219         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6220         {
6221                 x *= 2;
6222                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6223                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6224                 GL_Color(r,r,r,1);
6225                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6226                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6227                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6228                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6229
6230                 // copy the vertically blurred bloom view to a texture
6231                 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);
6232                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6233         }
6234
6235         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6236         brighten = r_bloom_brighten.value;
6237         if (r_bloomstate.hdr)
6238                 brighten *= r_hdr_range.value;
6239         brighten = sqrt(brighten);
6240         if(range >= 1)
6241                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6242         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6243
6244         for (dir = 0;dir < 2;dir++)
6245         {
6246                 // blend on at multiple vertical offsets to achieve a vertical blur
6247                 // TODO: do offset blends using GLSL
6248                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6249                 GL_BlendFunc(GL_ONE, GL_ZERO);
6250                 for (x = -range;x <= range;x++)
6251                 {
6252                         if (!dir){xoffset = 0;yoffset = x;}
6253                         else {xoffset = x;yoffset = 0;}
6254                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6255                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6256                         // compute a texcoord array with the specified x and y offset
6257                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6258                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6259                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6260                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6261                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6262                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6263                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6264                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6265                         // this r value looks like a 'dot' particle, fading sharply to
6266                         // black at the edges
6267                         // (probably not realistic but looks good enough)
6268                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6269                         //r = brighten/(range*2+1);
6270                         r = brighten / (range * 2 + 1);
6271                         if(range >= 1)
6272                                 r *= (1 - x*x/(float)(range*range));
6273                         GL_Color(r, r, r, 1);
6274                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6275                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6276                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6277                         GL_BlendFunc(GL_ONE, GL_ONE);
6278                 }
6279
6280                 // copy the vertically blurred bloom view to a texture
6281                 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);
6282                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6283         }
6284 }
6285
6286 void R_HDR_RenderBloomTexture(void)
6287 {
6288         int oldwidth, oldheight;
6289         float oldcolorscale;
6290         qboolean oldwaterstate;
6291
6292         oldwaterstate = r_waterstate.enabled;
6293         oldcolorscale = r_refdef.view.colorscale;
6294         oldwidth = r_refdef.view.width;
6295         oldheight = r_refdef.view.height;
6296         r_refdef.view.width = r_bloomstate.bloomwidth;
6297         r_refdef.view.height = r_bloomstate.bloomheight;
6298
6299         if(r_hdr.integer < 2)
6300                 r_waterstate.enabled = false;
6301
6302         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6303         // TODO: add exposure compensation features
6304         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6305
6306         r_refdef.view.showdebug = false;
6307         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6308
6309         R_ResetViewRendering3D();
6310
6311         R_ClearScreen(r_refdef.fogenabled);
6312         if (r_timereport_active)
6313                 R_TimeReport("HDRclear");
6314
6315         R_View_Update();
6316         if (r_timereport_active)
6317                 R_TimeReport("visibility");
6318
6319         // only do secondary renders with HDR if r_hdr is 2 or higher
6320         r_waterstate.numwaterplanes = 0;
6321         if (r_waterstate.enabled)
6322                 R_RenderWaterPlanes();
6323
6324         r_refdef.view.showdebug = true;
6325         R_RenderScene();
6326         r_waterstate.numwaterplanes = 0;
6327
6328         R_ResetViewRendering2D();
6329
6330         R_Bloom_CopyHDRTexture();
6331         R_Bloom_MakeTexture();
6332
6333         // restore the view settings
6334         r_waterstate.enabled = oldwaterstate;
6335         r_refdef.view.width = oldwidth;
6336         r_refdef.view.height = oldheight;
6337         r_refdef.view.colorscale = oldcolorscale;
6338
6339         R_ResetViewRendering3D();
6340
6341         R_ClearScreen(r_refdef.fogenabled);
6342         if (r_timereport_active)
6343                 R_TimeReport("viewclear");
6344 }
6345
6346 static void R_BlendView(void)
6347 {
6348         unsigned int permutation;
6349         float uservecs[4][4];
6350
6351         switch (vid.renderpath)
6352         {
6353         case RENDERPATH_GL20:
6354         case RENDERPATH_D3D9:
6355         case RENDERPATH_D3D10:
6356         case RENDERPATH_D3D11:
6357         case RENDERPATH_SOFT:
6358         case RENDERPATH_GLES2:
6359                 permutation =
6360                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6361                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6362                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6363                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6364                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6365
6366                 if (r_bloomstate.texture_screen)
6367                 {
6368                         // make sure the buffer is available
6369                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6370
6371                         R_ResetViewRendering2D();
6372                         R_Mesh_SetMainRenderTargets();
6373
6374                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6375                         {
6376                                 // declare variables
6377                                 float blur_factor, blur_mouseaccel, blur_velocity;
6378                                 static float blur_average; 
6379                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6380
6381                                 // set a goal for the factoring
6382                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6383                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6384                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6385                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6386                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6387                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6388
6389                                 // from the goal, pick an averaged value between goal and last value
6390                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6391                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6392                                 
6393                                 // enforce minimum amount of blur 
6394                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6395                                 
6396                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6397
6398                                 // calculate values into a standard alpha
6399                                 cl.motionbluralpha = 1 - exp(-
6400                                                 (
6401                                                  (r_motionblur.value * blur_factor / 80)
6402                                                  +
6403                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6404                                                 )
6405                                                 /
6406                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6407                                           );
6408                                 
6409                                 // randomization for the blur value to combat persistent ghosting
6410                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6411                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6412                                 
6413                                 // apply the blur
6414                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6415                                 {
6416                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6417                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6418                                         switch(vid.renderpath)
6419                                         {
6420                                         case RENDERPATH_GL11:
6421                                         case RENDERPATH_GL13:
6422                                         case RENDERPATH_GL20:
6423                                         case RENDERPATH_GLES1:
6424                                         case RENDERPATH_GLES2:
6425                                         case RENDERPATH_SOFT:
6426                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6427                                                 break;
6428                                         case RENDERPATH_D3D9:
6429                                         case RENDERPATH_D3D10:
6430                                         case RENDERPATH_D3D11:
6431                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6432                                                 break;
6433                                         }
6434                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6435                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6436                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6437                                 }
6438                                 
6439                                 // updates old view angles for next pass 
6440                                 VectorCopy(cl.viewangles, blur_oldangles);
6441                         }
6442
6443                         // copy view into the screen texture
6444                         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);
6445                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6446                 }
6447                 else if (!r_bloomstate.texture_bloom)
6448                 {
6449                         // we may still have to do view tint...
6450                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6451                         {
6452                                 // apply a color tint to the whole view
6453                                 R_ResetViewRendering2D();
6454                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6455                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6456                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6457                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6458                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6459                         }
6460                         break; // no screen processing, no bloom, skip it
6461                 }
6462
6463                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6464                 {
6465                         // render simple bloom effect
6466                         // copy the screen and shrink it and darken it for the bloom process
6467                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6468                         // make the bloom texture
6469                         R_Bloom_MakeTexture();
6470                 }
6471
6472 #if _MSC_VER >= 1400
6473 #define sscanf sscanf_s
6474 #endif
6475                 memset(uservecs, 0, sizeof(uservecs));
6476                 if (r_glsl_postprocess_uservec1_enable.integer)
6477                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6478                 if (r_glsl_postprocess_uservec2_enable.integer)
6479                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6480                 if (r_glsl_postprocess_uservec3_enable.integer)
6481                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6482                 if (r_glsl_postprocess_uservec4_enable.integer)
6483                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6484
6485                 R_ResetViewRendering2D();
6486                 GL_Color(1, 1, 1, 1);
6487                 GL_BlendFunc(GL_ONE, GL_ZERO);
6488
6489                 switch(vid.renderpath)
6490                 {
6491                 case RENDERPATH_GL20:
6492                 case RENDERPATH_GLES2:
6493                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6494                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6495                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6496                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6497                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6498                         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]);
6499                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6500                         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]);
6501                         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]);
6502                         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]);
6503                         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]);
6504                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6505                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6506                         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);
6507                         break;
6508                 case RENDERPATH_D3D9:
6509 #ifdef SUPPORTD3D
6510                         // 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...
6511                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6512                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6513                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6514                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6515                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6516                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6517                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6518                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6519                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6520                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6521                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6522                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6523                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6524                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6525 #endif
6526                         break;
6527                 case RENDERPATH_D3D10:
6528                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6529                         break;
6530                 case RENDERPATH_D3D11:
6531                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6532                         break;
6533                 case RENDERPATH_SOFT:
6534                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6535                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6536                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6537                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6538                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6539                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6540                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6541                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6542                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6543                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6544                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6545                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6546                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6547                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6548                         break;
6549                 default:
6550                         break;
6551                 }
6552                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6553                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6554                 break;
6555         case RENDERPATH_GL11:
6556         case RENDERPATH_GL13:
6557         case RENDERPATH_GLES1:
6558                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6559                 {
6560                         // apply a color tint to the whole view
6561                         R_ResetViewRendering2D();
6562                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6563                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6564                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6565                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6566                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6567                 }
6568                 break;
6569         }
6570 }
6571
6572 matrix4x4_t r_waterscrollmatrix;
6573
6574 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6575 {
6576         if (r_refdef.fog_density)
6577         {
6578                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6579                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6580                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6581
6582                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6583                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6584                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6585                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6586
6587                 {
6588                         vec3_t fogvec;
6589                         VectorCopy(r_refdef.fogcolor, fogvec);
6590                         //   color.rgb *= ContrastBoost * SceneBrightness;
6591                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6592                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6593                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6594                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6595                 }
6596         }
6597 }
6598
6599 void R_UpdateVariables(void)
6600 {
6601         R_Textures_Frame();
6602
6603         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6604
6605         r_refdef.farclip = r_farclip_base.value;
6606         if (r_refdef.scene.worldmodel)
6607                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6608         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6609
6610         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6611                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6612         r_refdef.polygonfactor = 0;
6613         r_refdef.polygonoffset = 0;
6614         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6615         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6616
6617         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6618         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6619         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6620         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6621         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6622         if (FAKELIGHT_ENABLED)
6623         {
6624                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6625         }
6626         if (r_showsurfaces.integer)
6627         {
6628                 r_refdef.scene.rtworld = false;
6629                 r_refdef.scene.rtworldshadows = false;
6630                 r_refdef.scene.rtdlight = false;
6631                 r_refdef.scene.rtdlightshadows = false;
6632                 r_refdef.lightmapintensity = 0;
6633         }
6634
6635         if (gamemode == GAME_NEHAHRA)
6636         {
6637                 if (gl_fogenable.integer)
6638                 {
6639                         r_refdef.oldgl_fogenable = true;
6640                         r_refdef.fog_density = gl_fogdensity.value;
6641                         r_refdef.fog_red = gl_fogred.value;
6642                         r_refdef.fog_green = gl_foggreen.value;
6643                         r_refdef.fog_blue = gl_fogblue.value;
6644                         r_refdef.fog_alpha = 1;
6645                         r_refdef.fog_start = 0;
6646                         r_refdef.fog_end = gl_skyclip.value;
6647                         r_refdef.fog_height = 1<<30;
6648                         r_refdef.fog_fadedepth = 128;
6649                 }
6650                 else if (r_refdef.oldgl_fogenable)
6651                 {
6652                         r_refdef.oldgl_fogenable = false;
6653                         r_refdef.fog_density = 0;
6654                         r_refdef.fog_red = 0;
6655                         r_refdef.fog_green = 0;
6656                         r_refdef.fog_blue = 0;
6657                         r_refdef.fog_alpha = 0;
6658                         r_refdef.fog_start = 0;
6659                         r_refdef.fog_end = 0;
6660                         r_refdef.fog_height = 1<<30;
6661                         r_refdef.fog_fadedepth = 128;
6662                 }
6663         }
6664
6665         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6666         r_refdef.fog_start = max(0, r_refdef.fog_start);
6667         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6668
6669         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6670
6671         if (r_refdef.fog_density && r_drawfog.integer)
6672         {
6673                 r_refdef.fogenabled = true;
6674                 // this is the point where the fog reaches 0.9986 alpha, which we
6675                 // consider a good enough cutoff point for the texture
6676                 // (0.9986 * 256 == 255.6)
6677                 if (r_fog_exp2.integer)
6678                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6679                 else
6680                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6681                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6682                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6683                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6684                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6685                         R_BuildFogHeightTexture();
6686                 // fog color was already set
6687                 // update the fog texture
6688                 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)
6689                         R_BuildFogTexture();
6690                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6691                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6692         }
6693         else
6694                 r_refdef.fogenabled = false;
6695
6696         switch(vid.renderpath)
6697         {
6698         case RENDERPATH_GL20:
6699         case RENDERPATH_D3D9:
6700         case RENDERPATH_D3D10:
6701         case RENDERPATH_D3D11:
6702         case RENDERPATH_SOFT:
6703         case RENDERPATH_GLES2:
6704                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6705                 {
6706                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6707                         {
6708                                 // build GLSL gamma texture
6709 #define RAMPWIDTH 256
6710                                 unsigned short ramp[RAMPWIDTH * 3];
6711                                 unsigned char rampbgr[RAMPWIDTH][4];
6712                                 int i;
6713
6714                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6715
6716                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6717                                 for(i = 0; i < RAMPWIDTH; ++i)
6718                                 {
6719                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6720                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6721                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6722                                         rampbgr[i][3] = 0;
6723                                 }
6724                                 if (r_texture_gammaramps)
6725                                 {
6726                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6727                                 }
6728                                 else
6729                                 {
6730                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6731                                 }
6732                         }
6733                 }
6734                 else
6735                 {
6736                         // remove GLSL gamma texture
6737                 }
6738                 break;
6739         case RENDERPATH_GL11:
6740         case RENDERPATH_GL13:
6741         case RENDERPATH_GLES1:
6742                 break;
6743         }
6744 }
6745
6746 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6747 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6748 /*
6749 ================
6750 R_SelectScene
6751 ================
6752 */
6753 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6754         if( scenetype != r_currentscenetype ) {
6755                 // store the old scenetype
6756                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6757                 r_currentscenetype = scenetype;
6758                 // move in the new scene
6759                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6760         }
6761 }
6762
6763 /*
6764 ================
6765 R_GetScenePointer
6766 ================
6767 */
6768 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6769 {
6770         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6771         if( scenetype == r_currentscenetype ) {
6772                 return &r_refdef.scene;
6773         } else {
6774                 return &r_scenes_store[ scenetype ];
6775         }
6776 }
6777
6778 int R_SortEntities_Compare(const void *ap, const void *bp)
6779 {
6780         const entity_render_t *a = *(const entity_render_t **)ap;
6781         const entity_render_t *b = *(const entity_render_t **)bp;
6782
6783         // 1. compare model
6784         if(a->model < b->model)
6785                 return -1;
6786         if(a->model > b->model)
6787                 return +1;
6788
6789         // 2. compare skin
6790         // TODO possibly calculate the REAL skinnum here first using
6791         // skinscenes?
6792         if(a->skinnum < b->skinnum)
6793                 return -1;
6794         if(a->skinnum > b->skinnum)
6795                 return +1;
6796
6797         // everything we compared is equal
6798         return 0;
6799 }
6800 void R_SortEntities(void)
6801 {
6802         // below or equal 2 ents, sorting never gains anything
6803         if(r_refdef.scene.numentities <= 2)
6804                 return;
6805         // sort
6806         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6807 }
6808
6809 /*
6810 ================
6811 R_RenderView
6812 ================
6813 */
6814 int dpsoftrast_test;
6815 extern void R_Shadow_UpdateBounceGridTexture(void);
6816 extern cvar_t r_shadow_bouncegrid;
6817 void R_RenderView(void)
6818 {
6819         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6820
6821         dpsoftrast_test = r_test.integer;
6822
6823         if (r_timereport_active)
6824                 R_TimeReport("start");
6825         r_textureframe++; // used only by R_GetCurrentTexture
6826         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6827
6828         if(R_CompileShader_CheckStaticParms())
6829                 R_GLSL_Restart_f();
6830
6831         if (!r_drawentities.integer)
6832                 r_refdef.scene.numentities = 0;
6833         else if (r_sortentities.integer)
6834                 R_SortEntities();
6835
6836         R_AnimCache_ClearCache();
6837         R_FrameData_NewFrame();
6838
6839         /* adjust for stereo display */
6840         if(R_Stereo_Active())
6841         {
6842                 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);
6843                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6844         }
6845
6846         if (r_refdef.view.isoverlay)
6847         {
6848                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6849                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6850                 R_TimeReport("depthclear");
6851
6852                 r_refdef.view.showdebug = false;
6853
6854                 r_waterstate.enabled = false;
6855                 r_waterstate.numwaterplanes = 0;
6856
6857                 R_RenderScene();
6858
6859                 r_refdef.view.matrix = originalmatrix;
6860
6861                 CHECKGLERROR
6862                 return;
6863         }
6864
6865         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6866         {
6867                 r_refdef.view.matrix = originalmatrix;
6868                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6869         }
6870
6871         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6872
6873         R_RenderView_UpdateViewVectors();
6874
6875         R_Shadow_UpdateWorldLightSelection();
6876
6877         R_Bloom_StartFrame();
6878         R_Water_StartFrame();
6879
6880         CHECKGLERROR
6881         if (r_timereport_active)
6882                 R_TimeReport("viewsetup");
6883
6884         R_ResetViewRendering3D();
6885
6886         if (r_refdef.view.clear || r_refdef.fogenabled)
6887         {
6888                 R_ClearScreen(r_refdef.fogenabled);
6889                 if (r_timereport_active)
6890                         R_TimeReport("viewclear");
6891         }
6892         r_refdef.view.clear = true;
6893
6894         // this produces a bloom texture to be used in R_BlendView() later
6895         if (r_bloomstate.hdr)
6896         {
6897                 R_HDR_RenderBloomTexture();
6898                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6899                 r_textureframe++; // used only by R_GetCurrentTexture
6900         }
6901
6902         r_refdef.view.showdebug = true;
6903
6904         R_View_Update();
6905         if (r_timereport_active)
6906                 R_TimeReport("visibility");
6907
6908         R_Shadow_UpdateBounceGridTexture();
6909         if (r_timereport_active && r_shadow_bouncegrid.integer)
6910                 R_TimeReport("bouncegrid");
6911
6912         r_waterstate.numwaterplanes = 0;
6913         if (r_waterstate.enabled)
6914                 R_RenderWaterPlanes();
6915
6916         R_RenderScene();
6917         r_waterstate.numwaterplanes = 0;
6918
6919         R_BlendView();
6920         if (r_timereport_active)
6921                 R_TimeReport("blendview");
6922
6923         GL_Scissor(0, 0, vid.width, vid.height);
6924         GL_ScissorTest(false);
6925
6926         r_refdef.view.matrix = originalmatrix;
6927
6928         CHECKGLERROR
6929 }
6930
6931 void R_RenderWaterPlanes(void)
6932 {
6933         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6934         {
6935                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6936                 if (r_timereport_active)
6937                         R_TimeReport("waterworld");
6938         }
6939
6940         // don't let sound skip if going slow
6941         if (r_refdef.scene.extraupdate)
6942                 S_ExtraUpdate ();
6943
6944         R_DrawModelsAddWaterPlanes();
6945         if (r_timereport_active)
6946                 R_TimeReport("watermodels");
6947
6948         if (r_waterstate.numwaterplanes)
6949         {
6950                 R_Water_ProcessPlanes();
6951                 if (r_timereport_active)
6952                         R_TimeReport("waterscenes");
6953         }
6954 }
6955
6956 extern void R_DrawLightningBeams (void);
6957 extern void VM_CL_AddPolygonsToMeshQueue (void);
6958 extern void R_DrawPortals (void);
6959 extern cvar_t cl_locs_show;
6960 static void R_DrawLocs(void);
6961 static void R_DrawEntityBBoxes(void);
6962 static void R_DrawModelDecals(void);
6963 extern void R_DrawModelShadows(void);
6964 extern void R_DrawModelShadowMaps(void);
6965 extern cvar_t cl_decals_newsystem;
6966 extern qboolean r_shadow_usingdeferredprepass;
6967 void R_RenderScene(void)
6968 {
6969         qboolean shadowmapping = false;
6970
6971         if (r_timereport_active)
6972                 R_TimeReport("beginscene");
6973
6974         r_refdef.stats.renders++;
6975
6976         R_UpdateFogColor();
6977
6978         // don't let sound skip if going slow
6979         if (r_refdef.scene.extraupdate)
6980                 S_ExtraUpdate ();
6981
6982         R_MeshQueue_BeginScene();
6983
6984         R_SkyStartFrame();
6985
6986         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);
6987
6988         if (r_timereport_active)
6989                 R_TimeReport("skystartframe");
6990
6991         if (cl.csqc_vidvars.drawworld)
6992         {
6993                 // don't let sound skip if going slow
6994                 if (r_refdef.scene.extraupdate)
6995                         S_ExtraUpdate ();
6996
6997                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6998                 {
6999                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7000                         if (r_timereport_active)
7001                                 R_TimeReport("worldsky");
7002                 }
7003
7004                 if (R_DrawBrushModelsSky() && r_timereport_active)
7005                         R_TimeReport("bmodelsky");
7006
7007                 if (skyrendermasked && skyrenderlater)
7008                 {
7009                         // we have to force off the water clipping plane while rendering sky
7010                         R_SetupView(false);
7011                         R_Sky();
7012                         R_SetupView(true);
7013                         if (r_timereport_active)
7014                                 R_TimeReport("sky");
7015                 }
7016         }
7017
7018         R_AnimCache_CacheVisibleEntities();
7019         if (r_timereport_active)
7020                 R_TimeReport("animation");
7021
7022         R_Shadow_PrepareLights();
7023         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7024                 R_Shadow_PrepareModelShadows();
7025         if (r_timereport_active)
7026                 R_TimeReport("preparelights");
7027
7028         if (R_Shadow_ShadowMappingEnabled())
7029                 shadowmapping = true;
7030
7031         if (r_shadow_usingdeferredprepass)
7032                 R_Shadow_DrawPrepass();
7033
7034         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7035         {
7036                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7037                 if (r_timereport_active)
7038                         R_TimeReport("worlddepth");
7039         }
7040         if (r_depthfirst.integer >= 2)
7041         {
7042                 R_DrawModelsDepth();
7043                 if (r_timereport_active)
7044                         R_TimeReport("modeldepth");
7045         }
7046
7047         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7048         {
7049                 R_DrawModelShadowMaps();
7050                 R_ResetViewRendering3D();
7051                 // don't let sound skip if going slow
7052                 if (r_refdef.scene.extraupdate)
7053                         S_ExtraUpdate ();
7054         }
7055
7056         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7057         {
7058                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7059                 if (r_timereport_active)
7060                         R_TimeReport("world");
7061         }
7062
7063         // don't let sound skip if going slow
7064         if (r_refdef.scene.extraupdate)
7065                 S_ExtraUpdate ();
7066
7067         R_DrawModels();
7068         if (r_timereport_active)
7069                 R_TimeReport("models");
7070
7071         // don't let sound skip if going slow
7072         if (r_refdef.scene.extraupdate)
7073                 S_ExtraUpdate ();
7074
7075         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7076         {
7077                 R_DrawModelShadows();
7078                 R_ResetViewRendering3D();
7079                 // don't let sound skip if going slow
7080                 if (r_refdef.scene.extraupdate)
7081                         S_ExtraUpdate ();
7082         }
7083
7084         if (!r_shadow_usingdeferredprepass)
7085         {
7086                 R_Shadow_DrawLights();
7087                 if (r_timereport_active)
7088                         R_TimeReport("rtlights");
7089         }
7090
7091         // don't let sound skip if going slow
7092         if (r_refdef.scene.extraupdate)
7093                 S_ExtraUpdate ();
7094
7095         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7096         {
7097                 R_DrawModelShadows();
7098                 R_ResetViewRendering3D();
7099                 // don't let sound skip if going slow
7100                 if (r_refdef.scene.extraupdate)
7101                         S_ExtraUpdate ();
7102         }
7103
7104         if (cl.csqc_vidvars.drawworld)
7105         {
7106                 if (cl_decals_newsystem.integer)
7107                 {
7108                         R_DrawModelDecals();
7109                         if (r_timereport_active)
7110                                 R_TimeReport("modeldecals");
7111                 }
7112                 else
7113                 {
7114                         R_DrawDecals();
7115                         if (r_timereport_active)
7116                                 R_TimeReport("decals");
7117                 }
7118
7119                 R_DrawParticles();
7120                 if (r_timereport_active)
7121                         R_TimeReport("particles");
7122
7123                 R_DrawExplosions();
7124                 if (r_timereport_active)
7125                         R_TimeReport("explosions");
7126
7127                 R_DrawLightningBeams();
7128                 if (r_timereport_active)
7129                         R_TimeReport("lightning");
7130         }
7131
7132         VM_CL_AddPolygonsToMeshQueue();
7133
7134         if (r_refdef.view.showdebug)
7135         {
7136                 if (cl_locs_show.integer)
7137                 {
7138                         R_DrawLocs();
7139                         if (r_timereport_active)
7140                                 R_TimeReport("showlocs");
7141                 }
7142
7143                 if (r_drawportals.integer)
7144                 {
7145                         R_DrawPortals();
7146                         if (r_timereport_active)
7147                                 R_TimeReport("portals");
7148                 }
7149
7150                 if (r_showbboxes.value > 0)
7151                 {
7152                         R_DrawEntityBBoxes();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("bboxes");
7155                 }
7156         }
7157
7158         if (r_transparent.integer)
7159         {
7160                 R_MeshQueue_RenderTransparent();
7161                 if (r_timereport_active)
7162                         R_TimeReport("drawtrans");
7163         }
7164
7165         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))
7166         {
7167                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7168                 if (r_timereport_active)
7169                         R_TimeReport("worlddebug");
7170                 R_DrawModelsDebug();
7171                 if (r_timereport_active)
7172                         R_TimeReport("modeldebug");
7173         }
7174
7175         if (cl.csqc_vidvars.drawworld)
7176         {
7177                 R_Shadow_DrawCoronas();
7178                 if (r_timereport_active)
7179                         R_TimeReport("coronas");
7180         }
7181
7182 #if 0
7183         {
7184                 GL_DepthTest(false);
7185                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7186                 GL_Color(1, 1, 1, 1);
7187                 qglBegin(GL_POLYGON);
7188                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7189                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7190                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7191                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7192                 qglEnd();
7193                 qglBegin(GL_POLYGON);
7194                 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]);
7195                 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]);
7196                 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]);
7197                 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]);
7198                 qglEnd();
7199                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7200         }
7201 #endif
7202
7203         // don't let sound skip if going slow
7204         if (r_refdef.scene.extraupdate)
7205                 S_ExtraUpdate ();
7206
7207         R_ResetViewRendering2D();
7208 }
7209
7210 static const unsigned short bboxelements[36] =
7211 {
7212         5, 1, 3, 5, 3, 7,
7213         6, 2, 0, 6, 0, 4,
7214         7, 3, 2, 7, 2, 6,
7215         4, 0, 1, 4, 1, 5,
7216         4, 5, 7, 4, 7, 6,
7217         1, 0, 2, 1, 2, 3,
7218 };
7219
7220 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7221 {
7222         int i;
7223         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7224
7225         RSurf_ActiveWorldEntity();
7226
7227         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7228         GL_DepthMask(false);
7229         GL_DepthRange(0, 1);
7230         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7231 //      R_Mesh_ResetTextureState();
7232
7233         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7234         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7235         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7236         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7237         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7238         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7239         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7240         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7241         R_FillColors(color4f, 8, cr, cg, cb, ca);
7242         if (r_refdef.fogenabled)
7243         {
7244                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7245                 {
7246                         f1 = RSurf_FogVertex(v);
7247                         f2 = 1 - f1;
7248                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7249                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7250                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7251                 }
7252         }
7253         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7254         R_Mesh_ResetTextureState();
7255         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7256         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7257 }
7258
7259 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7260 {
7261         int i;
7262         float color[4];
7263         prvm_edict_t *edict;
7264         prvm_prog_t *prog_save = prog;
7265
7266         // this function draws bounding boxes of server entities
7267         if (!sv.active)
7268                 return;
7269
7270         GL_CullFace(GL_NONE);
7271         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7272
7273         prog = 0;
7274         SV_VM_Begin();
7275         for (i = 0;i < numsurfaces;i++)
7276         {
7277                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7278                 switch ((int)PRVM_serveredictfloat(edict, solid))
7279                 {
7280                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7281                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7282                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7283                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7284                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7285                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7286                 }
7287                 color[3] *= r_showbboxes.value;
7288                 color[3] = bound(0, color[3], 1);
7289                 GL_DepthTest(!r_showdisabledepthtest.integer);
7290                 GL_CullFace(r_refdef.view.cullface_front);
7291                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7292         }
7293         SV_VM_End();
7294         prog = prog_save;
7295 }
7296
7297 static void R_DrawEntityBBoxes(void)
7298 {
7299         int i;
7300         prvm_edict_t *edict;
7301         vec3_t center;
7302         prvm_prog_t *prog_save = prog;
7303
7304         // this function draws bounding boxes of server entities
7305         if (!sv.active)
7306                 return;
7307
7308         prog = 0;
7309         SV_VM_Begin();
7310         for (i = 0;i < prog->num_edicts;i++)
7311         {
7312                 edict = PRVM_EDICT_NUM(i);
7313                 if (edict->priv.server->free)
7314                         continue;
7315                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7316                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7317                         continue;
7318                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7319                         continue;
7320                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7321                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7322         }
7323         SV_VM_End();
7324         prog = prog_save;
7325 }
7326
7327 static const int nomodelelement3i[24] =
7328 {
7329         5, 2, 0,
7330         5, 1, 2,
7331         5, 0, 3,
7332         5, 3, 1,
7333         0, 2, 4,
7334         2, 1, 4,
7335         3, 0, 4,
7336         1, 3, 4
7337 };
7338
7339 static const unsigned short nomodelelement3s[24] =
7340 {
7341         5, 2, 0,
7342         5, 1, 2,
7343         5, 0, 3,
7344         5, 3, 1,
7345         0, 2, 4,
7346         2, 1, 4,
7347         3, 0, 4,
7348         1, 3, 4
7349 };
7350
7351 static const float nomodelvertex3f[6*3] =
7352 {
7353         -16,   0,   0,
7354          16,   0,   0,
7355           0, -16,   0,
7356           0,  16,   0,
7357           0,   0, -16,
7358           0,   0,  16
7359 };
7360
7361 static const float nomodelcolor4f[6*4] =
7362 {
7363         0.0f, 0.0f, 0.5f, 1.0f,
7364         0.0f, 0.0f, 0.5f, 1.0f,
7365         0.0f, 0.5f, 0.0f, 1.0f,
7366         0.0f, 0.5f, 0.0f, 1.0f,
7367         0.5f, 0.0f, 0.0f, 1.0f,
7368         0.5f, 0.0f, 0.0f, 1.0f
7369 };
7370
7371 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7372 {
7373         int i;
7374         float f1, f2, *c;
7375         float color4f[6*4];
7376
7377         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);
7378
7379         // this is only called once per entity so numsurfaces is always 1, and
7380         // surfacelist is always {0}, so this code does not handle batches
7381
7382         if (rsurface.ent_flags & RENDER_ADDITIVE)
7383         {
7384                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7385                 GL_DepthMask(false);
7386         }
7387         else if (rsurface.colormod[3] < 1)
7388         {
7389                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7390                 GL_DepthMask(false);
7391         }
7392         else
7393         {
7394                 GL_BlendFunc(GL_ONE, GL_ZERO);
7395                 GL_DepthMask(true);
7396         }
7397         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7398         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7399         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7400         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7401         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7402         for (i = 0, c = color4f;i < 6;i++, c += 4)
7403         {
7404                 c[0] *= rsurface.colormod[0];
7405                 c[1] *= rsurface.colormod[1];
7406                 c[2] *= rsurface.colormod[2];
7407                 c[3] *= rsurface.colormod[3];
7408         }
7409         if (r_refdef.fogenabled)
7410         {
7411                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7412                 {
7413                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7414                         f2 = 1 - f1;
7415                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7416                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7417                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7418                 }
7419         }
7420 //      R_Mesh_ResetTextureState();
7421         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7422         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7423         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7424 }
7425
7426 void R_DrawNoModel(entity_render_t *ent)
7427 {
7428         vec3_t org;
7429         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7430         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7431                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7432         else
7433                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7434 }
7435
7436 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7437 {
7438         vec3_t right1, right2, diff, normal;
7439
7440         VectorSubtract (org2, org1, normal);
7441
7442         // calculate 'right' vector for start
7443         VectorSubtract (r_refdef.view.origin, org1, diff);
7444         CrossProduct (normal, diff, right1);
7445         VectorNormalize (right1);
7446
7447         // calculate 'right' vector for end
7448         VectorSubtract (r_refdef.view.origin, org2, diff);
7449         CrossProduct (normal, diff, right2);
7450         VectorNormalize (right2);
7451
7452         vert[ 0] = org1[0] + width * right1[0];
7453         vert[ 1] = org1[1] + width * right1[1];
7454         vert[ 2] = org1[2] + width * right1[2];
7455         vert[ 3] = org1[0] - width * right1[0];
7456         vert[ 4] = org1[1] - width * right1[1];
7457         vert[ 5] = org1[2] - width * right1[2];
7458         vert[ 6] = org2[0] - width * right2[0];
7459         vert[ 7] = org2[1] - width * right2[1];
7460         vert[ 8] = org2[2] - width * right2[2];
7461         vert[ 9] = org2[0] + width * right2[0];
7462         vert[10] = org2[1] + width * right2[1];
7463         vert[11] = org2[2] + width * right2[2];
7464 }
7465
7466 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)
7467 {
7468         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7469         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7470         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7471         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7472         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7473         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7474         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7475         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7476         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7477         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7478         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7479         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7480 }
7481
7482 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7483 {
7484         int i;
7485         float *vertex3f;
7486         float v[3];
7487         VectorSet(v, x, y, z);
7488         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7489                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7490                         break;
7491         if (i == mesh->numvertices)
7492         {
7493                 if (mesh->numvertices < mesh->maxvertices)
7494                 {
7495                         VectorCopy(v, vertex3f);
7496                         mesh->numvertices++;
7497                 }
7498                 return mesh->numvertices;
7499         }
7500         else
7501                 return i;
7502 }
7503
7504 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7505 {
7506         int i;
7507         int *e, element[3];
7508         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7509         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7510         e = mesh->element3i + mesh->numtriangles * 3;
7511         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7512         {
7513                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7514                 if (mesh->numtriangles < mesh->maxtriangles)
7515                 {
7516                         *e++ = element[0];
7517                         *e++ = element[1];
7518                         *e++ = element[2];
7519                         mesh->numtriangles++;
7520                 }
7521                 element[1] = element[2];
7522         }
7523 }
7524
7525 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7526 {
7527         int i;
7528         int *e, element[3];
7529         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7530         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7531         e = mesh->element3i + mesh->numtriangles * 3;
7532         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7533         {
7534                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7535                 if (mesh->numtriangles < mesh->maxtriangles)
7536                 {
7537                         *e++ = element[0];
7538                         *e++ = element[1];
7539                         *e++ = element[2];
7540                         mesh->numtriangles++;
7541                 }
7542                 element[1] = element[2];
7543         }
7544 }
7545
7546 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7547 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7548 {
7549         int planenum, planenum2;
7550         int w;
7551         int tempnumpoints;
7552         mplane_t *plane, *plane2;
7553         double maxdist;
7554         double temppoints[2][256*3];
7555         // figure out how large a bounding box we need to properly compute this brush
7556         maxdist = 0;
7557         for (w = 0;w < numplanes;w++)
7558                 maxdist = max(maxdist, fabs(planes[w].dist));
7559         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7560         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7561         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7562         {
7563                 w = 0;
7564                 tempnumpoints = 4;
7565                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7566                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7567                 {
7568                         if (planenum2 == planenum)
7569                                 continue;
7570                         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);
7571                         w = !w;
7572                 }
7573                 if (tempnumpoints < 3)
7574                         continue;
7575                 // generate elements forming a triangle fan for this polygon
7576                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7577         }
7578 }
7579
7580 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)
7581 {
7582         texturelayer_t *layer;
7583         layer = t->currentlayers + t->currentnumlayers++;
7584         layer->type = type;
7585         layer->depthmask = depthmask;
7586         layer->blendfunc1 = blendfunc1;
7587         layer->blendfunc2 = blendfunc2;
7588         layer->texture = texture;
7589         layer->texmatrix = *matrix;
7590         layer->color[0] = r;
7591         layer->color[1] = g;
7592         layer->color[2] = b;
7593         layer->color[3] = a;
7594 }
7595
7596 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7597 {
7598         if(parms[0] == 0 && parms[1] == 0)
7599                 return false;
7600         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7601                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7602                         return false;
7603         return true;
7604 }
7605
7606 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7607 {
7608         double index, f;
7609         index = parms[2] + rsurface.shadertime * parms[3];
7610         index -= floor(index);
7611         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7612         {
7613         default:
7614         case Q3WAVEFUNC_NONE:
7615         case Q3WAVEFUNC_NOISE:
7616         case Q3WAVEFUNC_COUNT:
7617                 f = 0;
7618                 break;
7619         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7620         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7621         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7622         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7623         case Q3WAVEFUNC_TRIANGLE:
7624                 index *= 4;
7625                 f = index - floor(index);
7626                 if (index < 1)
7627                 {
7628                         // f = f;
7629                 }
7630                 else if (index < 2)
7631                         f = 1 - f;
7632                 else if (index < 3)
7633                         f = -f;
7634                 else
7635                         f = -(1 - f);
7636                 break;
7637         }
7638         f = parms[0] + parms[1] * f;
7639         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7640                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7641         return (float) f;
7642 }
7643
7644 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7645 {
7646         int w, h, idx;
7647         double f;
7648         double offsetd[2];
7649         float tcmat[12];
7650         matrix4x4_t matrix, temp;
7651         switch(tcmod->tcmod)
7652         {
7653                 case Q3TCMOD_COUNT:
7654                 case Q3TCMOD_NONE:
7655                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7656                                 matrix = r_waterscrollmatrix;
7657                         else
7658                                 matrix = identitymatrix;
7659                         break;
7660                 case Q3TCMOD_ENTITYTRANSLATE:
7661                         // this is used in Q3 to allow the gamecode to control texcoord
7662                         // scrolling on the entity, which is not supported in darkplaces yet.
7663                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7664                         break;
7665                 case Q3TCMOD_ROTATE:
7666                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7667                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7668                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7669                         break;
7670                 case Q3TCMOD_SCALE:
7671                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7672                         break;
7673                 case Q3TCMOD_SCROLL:
7674                         // extra care is needed because of precision breakdown with large values of time
7675                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7676                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7677                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7678                         break;
7679                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7680                         w = (int) tcmod->parms[0];
7681                         h = (int) tcmod->parms[1];
7682                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7683                         f = f - floor(f);
7684                         idx = (int) floor(f * w * h);
7685                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7686                         break;
7687                 case Q3TCMOD_STRETCH:
7688                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7689                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7690                         break;
7691                 case Q3TCMOD_TRANSFORM:
7692                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7693                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7694                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7695                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7696                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7697                         break;
7698                 case Q3TCMOD_TURBULENT:
7699                         // this is handled in the RSurf_PrepareVertices function
7700                         matrix = identitymatrix;
7701                         break;
7702         }
7703         temp = *texmatrix;
7704         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7705 }
7706
7707 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7708 {
7709         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7710         char name[MAX_QPATH];
7711         skinframe_t *skinframe;
7712         unsigned char pixels[296*194];
7713         strlcpy(cache->name, skinname, sizeof(cache->name));
7714         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7715         if (developer_loading.integer)
7716                 Con_Printf("loading %s\n", name);
7717         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7718         if (!skinframe || !skinframe->base)
7719         {
7720                 unsigned char *f;
7721                 fs_offset_t filesize;
7722                 skinframe = NULL;
7723                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7724                 if (f)
7725                 {
7726                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7727                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7728                         Mem_Free(f);
7729                 }
7730         }
7731         cache->skinframe = skinframe;
7732 }
7733
7734 texture_t *R_GetCurrentTexture(texture_t *t)
7735 {
7736         int i;
7737         const entity_render_t *ent = rsurface.entity;
7738         dp_model_t *model = ent->model;
7739         q3shaderinfo_layer_tcmod_t *tcmod;
7740
7741         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7742                 return t->currentframe;
7743         t->update_lastrenderframe = r_textureframe;
7744         t->update_lastrenderentity = (void *)ent;
7745
7746         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7747                 t->camera_entity = ent->entitynumber;
7748         else
7749                 t->camera_entity = 0;
7750
7751         // switch to an alternate material if this is a q1bsp animated material
7752         {
7753                 texture_t *texture = t;
7754                 int s = rsurface.ent_skinnum;
7755                 if ((unsigned int)s >= (unsigned int)model->numskins)
7756                         s = 0;
7757                 if (model->skinscenes)
7758                 {
7759                         if (model->skinscenes[s].framecount > 1)
7760                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7761                         else
7762                                 s = model->skinscenes[s].firstframe;
7763                 }
7764                 if (s > 0)
7765                         t = t + s * model->num_surfaces;
7766                 if (t->animated)
7767                 {
7768                         // use an alternate animation if the entity's frame is not 0,
7769                         // and only if the texture has an alternate animation
7770                         if (rsurface.ent_alttextures && t->anim_total[1])
7771                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7772                         else
7773                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7774                 }
7775                 texture->currentframe = t;
7776         }
7777
7778         // update currentskinframe to be a qw skin or animation frame
7779         if (rsurface.ent_qwskin >= 0)
7780         {
7781                 i = rsurface.ent_qwskin;
7782                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7783                 {
7784                         r_qwskincache_size = cl.maxclients;
7785                         if (r_qwskincache)
7786                                 Mem_Free(r_qwskincache);
7787                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7788                 }
7789                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7790                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7791                 t->currentskinframe = r_qwskincache[i].skinframe;
7792                 if (t->currentskinframe == NULL)
7793                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7794         }
7795         else if (t->numskinframes >= 2)
7796                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7797         if (t->backgroundnumskinframes >= 2)
7798                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7799
7800         t->currentmaterialflags = t->basematerialflags;
7801         t->currentalpha = rsurface.colormod[3];
7802         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7803                 t->currentalpha *= r_wateralpha.value;
7804         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7805                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7806         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7807                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7808         if (!(rsurface.ent_flags & RENDER_LIGHT))
7809                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7810         else if (FAKELIGHT_ENABLED)
7811         {
7812                 // no modellight if using fakelight for the map
7813         }
7814         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7815         {
7816                 // pick a model lighting mode
7817                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7818                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7819                 else
7820                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7821         }
7822         if (rsurface.ent_flags & RENDER_ADDITIVE)
7823                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7824         else if (t->currentalpha < 1)
7825                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7826         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7827                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7828         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7829                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7830         if (t->backgroundnumskinframes)
7831                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7832         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7833         {
7834                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7835                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7836         }
7837         else
7838                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7839         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7840         {
7841                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7842                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7843         }
7844         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7845                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7846
7847         // there is no tcmod
7848         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7849         {
7850                 t->currenttexmatrix = r_waterscrollmatrix;
7851                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7852         }
7853         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7854         {
7855                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7856                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7857         }
7858
7859         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7860                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7861         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7862                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7863
7864         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7865         if (t->currentskinframe->qpixels)
7866                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7867         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7868         if (!t->basetexture)
7869                 t->basetexture = r_texture_notexture;
7870         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7871         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7872         t->nmaptexture = t->currentskinframe->nmap;
7873         if (!t->nmaptexture)
7874                 t->nmaptexture = r_texture_blanknormalmap;
7875         t->glosstexture = r_texture_black;
7876         t->glowtexture = t->currentskinframe->glow;
7877         t->fogtexture = t->currentskinframe->fog;
7878         t->reflectmasktexture = t->currentskinframe->reflect;
7879         if (t->backgroundnumskinframes)
7880         {
7881                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7882                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7883                 t->backgroundglosstexture = r_texture_black;
7884                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7885                 if (!t->backgroundnmaptexture)
7886                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7887         }
7888         else
7889         {
7890                 t->backgroundbasetexture = r_texture_white;
7891                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7892                 t->backgroundglosstexture = r_texture_black;
7893                 t->backgroundglowtexture = NULL;
7894         }
7895         t->specularpower = r_shadow_glossexponent.value;
7896         // TODO: store reference values for these in the texture?
7897         t->specularscale = 0;
7898         if (r_shadow_gloss.integer > 0)
7899         {
7900                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7901                 {
7902                         if (r_shadow_glossintensity.value > 0)
7903                         {
7904                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7905                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7906                                 t->specularscale = r_shadow_glossintensity.value;
7907                         }
7908                 }
7909                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7910                 {
7911                         t->glosstexture = r_texture_white;
7912                         t->backgroundglosstexture = r_texture_white;
7913                         t->specularscale = r_shadow_gloss2intensity.value;
7914                         t->specularpower = r_shadow_gloss2exponent.value;
7915                 }
7916         }
7917         t->specularscale *= t->specularscalemod;
7918         t->specularpower *= t->specularpowermod;
7919         t->rtlightambient = 0;
7920
7921         // lightmaps mode looks bad with dlights using actual texturing, so turn
7922         // off the colormap and glossmap, but leave the normalmap on as it still
7923         // accurately represents the shading involved
7924         if (gl_lightmaps.integer)
7925         {
7926                 t->basetexture = r_texture_grey128;
7927                 t->pantstexture = r_texture_black;
7928                 t->shirttexture = r_texture_black;
7929                 t->nmaptexture = r_texture_blanknormalmap;
7930                 t->glosstexture = r_texture_black;
7931                 t->glowtexture = NULL;
7932                 t->fogtexture = NULL;
7933                 t->reflectmasktexture = NULL;
7934                 t->backgroundbasetexture = NULL;
7935                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7936                 t->backgroundglosstexture = r_texture_black;
7937                 t->backgroundglowtexture = NULL;
7938                 t->specularscale = 0;
7939                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7940         }
7941
7942         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7943         VectorClear(t->dlightcolor);
7944         t->currentnumlayers = 0;
7945         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7946         {
7947                 int blendfunc1, blendfunc2;
7948                 qboolean depthmask;
7949                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7950                 {
7951                         blendfunc1 = GL_SRC_ALPHA;
7952                         blendfunc2 = GL_ONE;
7953                 }
7954                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7955                 {
7956                         blendfunc1 = GL_SRC_ALPHA;
7957                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7958                 }
7959                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7960                 {
7961                         blendfunc1 = t->customblendfunc[0];
7962                         blendfunc2 = t->customblendfunc[1];
7963                 }
7964                 else
7965                 {
7966                         blendfunc1 = GL_ONE;
7967                         blendfunc2 = GL_ZERO;
7968                 }
7969                 // don't colormod evilblend textures
7970                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7971                         VectorSet(t->lightmapcolor, 1, 1, 1);
7972                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7973                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7974                 {
7975                         // fullbright is not affected by r_refdef.lightmapintensity
7976                         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]);
7977                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7978                                 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]);
7979                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7980                                 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]);
7981                 }
7982                 else
7983                 {
7984                         vec3_t ambientcolor;
7985                         float colorscale;
7986                         // set the color tint used for lights affecting this surface
7987                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7988                         colorscale = 2;
7989                         // q3bsp has no lightmap updates, so the lightstylevalue that
7990                         // would normally be baked into the lightmap must be
7991                         // applied to the color
7992                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7993                         if (model->type == mod_brushq3)
7994                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7995                         colorscale *= r_refdef.lightmapintensity;
7996                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7997                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7998                         // basic lit geometry
7999                         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]);
8000                         // add pants/shirt if needed
8001                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8002                                 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]);
8003                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8004                                 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]);
8005                         // now add ambient passes if needed
8006                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8007                         {
8008                                 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]);
8009                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8010                                         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]);
8011                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8012                                         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]);
8013                         }
8014                 }
8015                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8016                         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]);
8017                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8018                 {
8019                         // if this is opaque use alpha blend which will darken the earlier
8020                         // passes cheaply.
8021                         //
8022                         // if this is an alpha blended material, all the earlier passes
8023                         // were darkened by fog already, so we only need to add the fog
8024                         // color ontop through the fog mask texture
8025                         //
8026                         // if this is an additive blended material, all the earlier passes
8027                         // were darkened by fog already, and we should not add fog color
8028                         // (because the background was not darkened, there is no fog color
8029                         // that was lost behind it).
8030                         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]);
8031                 }
8032         }
8033
8034         return t->currentframe;
8035 }
8036
8037 rsurfacestate_t rsurface;
8038
8039 void RSurf_ActiveWorldEntity(void)
8040 {
8041         dp_model_t *model = r_refdef.scene.worldmodel;
8042         //if (rsurface.entity == r_refdef.scene.worldentity)
8043         //      return;
8044         rsurface.entity = r_refdef.scene.worldentity;
8045         rsurface.skeleton = NULL;
8046         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8047         rsurface.ent_skinnum = 0;
8048         rsurface.ent_qwskin = -1;
8049         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8050         rsurface.shadertime = r_refdef.scene.time;
8051         rsurface.matrix = identitymatrix;
8052         rsurface.inversematrix = identitymatrix;
8053         rsurface.matrixscale = 1;
8054         rsurface.inversematrixscale = 1;
8055         R_EntityMatrix(&identitymatrix);
8056         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8057         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8058         rsurface.fograngerecip = r_refdef.fograngerecip;
8059         rsurface.fogheightfade = r_refdef.fogheightfade;
8060         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8061         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8062         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8063         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8064         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8065         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8066         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8067         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8068         rsurface.colormod[3] = 1;
8069         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);
8070         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8071         rsurface.frameblend[0].lerp = 1;
8072         rsurface.ent_alttextures = false;
8073         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8074         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8075         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8076         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8078         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8079         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8081         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8082         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8084         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8085         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8086         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8087         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8088         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8089         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8090         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8091         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8092         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8093         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8094         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8095         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8096         rsurface.modelelement3i = model->surfmesh.data_element3i;
8097         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8098         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8099         rsurface.modelelement3s = model->surfmesh.data_element3s;
8100         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8101         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8102         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8103         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8104         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8105         rsurface.modelsurfaces = model->data_surfaces;
8106         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8107         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8108         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8109         rsurface.modelgeneratedvertex = false;
8110         rsurface.batchgeneratedvertex = false;
8111         rsurface.batchfirstvertex = 0;
8112         rsurface.batchnumvertices = 0;
8113         rsurface.batchfirsttriangle = 0;
8114         rsurface.batchnumtriangles = 0;
8115         rsurface.batchvertex3f  = NULL;
8116         rsurface.batchvertex3f_vertexbuffer = NULL;
8117         rsurface.batchvertex3f_bufferoffset = 0;
8118         rsurface.batchsvector3f = NULL;
8119         rsurface.batchsvector3f_vertexbuffer = NULL;
8120         rsurface.batchsvector3f_bufferoffset = 0;
8121         rsurface.batchtvector3f = NULL;
8122         rsurface.batchtvector3f_vertexbuffer = NULL;
8123         rsurface.batchtvector3f_bufferoffset = 0;
8124         rsurface.batchnormal3f  = NULL;
8125         rsurface.batchnormal3f_vertexbuffer = NULL;
8126         rsurface.batchnormal3f_bufferoffset = 0;
8127         rsurface.batchlightmapcolor4f = NULL;
8128         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8129         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8130         rsurface.batchtexcoordtexture2f = NULL;
8131         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8132         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8133         rsurface.batchtexcoordlightmap2f = NULL;
8134         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8135         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8136         rsurface.batchvertexmesh = NULL;
8137         rsurface.batchvertexmeshbuffer = NULL;
8138         rsurface.batchvertex3fbuffer = NULL;
8139         rsurface.batchelement3i = NULL;
8140         rsurface.batchelement3i_indexbuffer = NULL;
8141         rsurface.batchelement3i_bufferoffset = 0;
8142         rsurface.batchelement3s = NULL;
8143         rsurface.batchelement3s_indexbuffer = NULL;
8144         rsurface.batchelement3s_bufferoffset = 0;
8145         rsurface.passcolor4f = NULL;
8146         rsurface.passcolor4f_vertexbuffer = NULL;
8147         rsurface.passcolor4f_bufferoffset = 0;
8148 }
8149
8150 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8151 {
8152         dp_model_t *model = ent->model;
8153         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8154         //      return;
8155         rsurface.entity = (entity_render_t *)ent;
8156         rsurface.skeleton = ent->skeleton;
8157         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8158         rsurface.ent_skinnum = ent->skinnum;
8159         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;
8160         rsurface.ent_flags = ent->flags;
8161         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8162         rsurface.matrix = ent->matrix;
8163         rsurface.inversematrix = ent->inversematrix;
8164         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8165         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8166         R_EntityMatrix(&rsurface.matrix);
8167         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8168         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8169         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8170         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8171         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8172         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8173         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8174         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8175         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8176         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8177         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8178         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8179         rsurface.colormod[3] = ent->alpha;
8180         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8181         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8182         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8183         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8184         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8185         if (ent->model->brush.submodel && !prepass)
8186         {
8187                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8188                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8189         }
8190         if (model->surfmesh.isanimated && model->AnimateVertices)
8191         {
8192                 if (ent->animcache_vertex3f)
8193                 {
8194                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8195                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8196                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8197                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8198                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8199                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8200                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8201                 }
8202                 else if (wanttangents)
8203                 {
8204                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8205                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8207                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8208                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8209                         rsurface.modelvertexmesh = NULL;
8210                         rsurface.modelvertexmeshbuffer = NULL;
8211                         rsurface.modelvertex3fbuffer = NULL;
8212                 }
8213                 else if (wantnormals)
8214                 {
8215                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8216                         rsurface.modelsvector3f = NULL;
8217                         rsurface.modeltvector3f = NULL;
8218                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8219                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8220                         rsurface.modelvertexmesh = NULL;
8221                         rsurface.modelvertexmeshbuffer = NULL;
8222                         rsurface.modelvertex3fbuffer = NULL;
8223                 }
8224                 else
8225                 {
8226                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8227                         rsurface.modelsvector3f = NULL;
8228                         rsurface.modeltvector3f = NULL;
8229                         rsurface.modelnormal3f = NULL;
8230                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8231                         rsurface.modelvertexmesh = NULL;
8232                         rsurface.modelvertexmeshbuffer = NULL;
8233                         rsurface.modelvertex3fbuffer = NULL;
8234                 }
8235                 rsurface.modelvertex3f_vertexbuffer = 0;
8236                 rsurface.modelvertex3f_bufferoffset = 0;
8237                 rsurface.modelsvector3f_vertexbuffer = 0;
8238                 rsurface.modelsvector3f_bufferoffset = 0;
8239                 rsurface.modeltvector3f_vertexbuffer = 0;
8240                 rsurface.modeltvector3f_bufferoffset = 0;
8241                 rsurface.modelnormal3f_vertexbuffer = 0;
8242                 rsurface.modelnormal3f_bufferoffset = 0;
8243                 rsurface.modelgeneratedvertex = true;
8244         }
8245         else
8246         {
8247                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8248                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8250                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8251                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8252                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8253                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8254                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8255                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8256                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8257                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8258                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8259                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8260                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8261                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8262                 rsurface.modelgeneratedvertex = false;
8263         }
8264         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8265         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8266         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8267         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8268         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8269         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8270         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8271         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8272         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8273         rsurface.modelelement3i = model->surfmesh.data_element3i;
8274         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8275         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8276         rsurface.modelelement3s = model->surfmesh.data_element3s;
8277         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8278         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8279         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8280         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8281         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8282         rsurface.modelsurfaces = model->data_surfaces;
8283         rsurface.batchgeneratedvertex = false;
8284         rsurface.batchfirstvertex = 0;
8285         rsurface.batchnumvertices = 0;
8286         rsurface.batchfirsttriangle = 0;
8287         rsurface.batchnumtriangles = 0;
8288         rsurface.batchvertex3f  = NULL;
8289         rsurface.batchvertex3f_vertexbuffer = NULL;
8290         rsurface.batchvertex3f_bufferoffset = 0;
8291         rsurface.batchsvector3f = NULL;
8292         rsurface.batchsvector3f_vertexbuffer = NULL;
8293         rsurface.batchsvector3f_bufferoffset = 0;
8294         rsurface.batchtvector3f = NULL;
8295         rsurface.batchtvector3f_vertexbuffer = NULL;
8296         rsurface.batchtvector3f_bufferoffset = 0;
8297         rsurface.batchnormal3f  = NULL;
8298         rsurface.batchnormal3f_vertexbuffer = NULL;
8299         rsurface.batchnormal3f_bufferoffset = 0;
8300         rsurface.batchlightmapcolor4f = NULL;
8301         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8302         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8303         rsurface.batchtexcoordtexture2f = NULL;
8304         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8305         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8306         rsurface.batchtexcoordlightmap2f = NULL;
8307         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8308         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8309         rsurface.batchvertexmesh = NULL;
8310         rsurface.batchvertexmeshbuffer = NULL;
8311         rsurface.batchvertex3fbuffer = NULL;
8312         rsurface.batchelement3i = NULL;
8313         rsurface.batchelement3i_indexbuffer = NULL;
8314         rsurface.batchelement3i_bufferoffset = 0;
8315         rsurface.batchelement3s = NULL;
8316         rsurface.batchelement3s_indexbuffer = NULL;
8317         rsurface.batchelement3s_bufferoffset = 0;
8318         rsurface.passcolor4f = NULL;
8319         rsurface.passcolor4f_vertexbuffer = NULL;
8320         rsurface.passcolor4f_bufferoffset = 0;
8321 }
8322
8323 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)
8324 {
8325         rsurface.entity = r_refdef.scene.worldentity;
8326         rsurface.skeleton = NULL;
8327         rsurface.ent_skinnum = 0;
8328         rsurface.ent_qwskin = -1;
8329         rsurface.ent_flags = entflags;
8330         rsurface.shadertime = r_refdef.scene.time - shadertime;
8331         rsurface.modelnumvertices = numvertices;
8332         rsurface.modelnumtriangles = numtriangles;
8333         rsurface.matrix = *matrix;
8334         rsurface.inversematrix = *inversematrix;
8335         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8336         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8337         R_EntityMatrix(&rsurface.matrix);
8338         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8339         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8340         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8341         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8342         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8343         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8344         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8345         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8346         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8347         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8348         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8349         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8350         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);
8351         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8352         rsurface.frameblend[0].lerp = 1;
8353         rsurface.ent_alttextures = false;
8354         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8355         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8356         if (wanttangents)
8357         {
8358                 rsurface.modelvertex3f = (float *)vertex3f;
8359                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8360                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8361                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8362         }
8363         else if (wantnormals)
8364         {
8365                 rsurface.modelvertex3f = (float *)vertex3f;
8366                 rsurface.modelsvector3f = NULL;
8367                 rsurface.modeltvector3f = NULL;
8368                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8369         }
8370         else
8371         {
8372                 rsurface.modelvertex3f = (float *)vertex3f;
8373                 rsurface.modelsvector3f = NULL;
8374                 rsurface.modeltvector3f = NULL;
8375                 rsurface.modelnormal3f = NULL;
8376         }
8377         rsurface.modelvertexmesh = NULL;
8378         rsurface.modelvertexmeshbuffer = NULL;
8379         rsurface.modelvertex3fbuffer = NULL;
8380         rsurface.modelvertex3f_vertexbuffer = 0;
8381         rsurface.modelvertex3f_bufferoffset = 0;
8382         rsurface.modelsvector3f_vertexbuffer = 0;
8383         rsurface.modelsvector3f_bufferoffset = 0;
8384         rsurface.modeltvector3f_vertexbuffer = 0;
8385         rsurface.modeltvector3f_bufferoffset = 0;
8386         rsurface.modelnormal3f_vertexbuffer = 0;
8387         rsurface.modelnormal3f_bufferoffset = 0;
8388         rsurface.modelgeneratedvertex = true;
8389         rsurface.modellightmapcolor4f  = (float *)color4f;
8390         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8391         rsurface.modellightmapcolor4f_bufferoffset = 0;
8392         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8393         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8394         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8395         rsurface.modeltexcoordlightmap2f  = NULL;
8396         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8397         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8398         rsurface.modelelement3i = (int *)element3i;
8399         rsurface.modelelement3i_indexbuffer = NULL;
8400         rsurface.modelelement3i_bufferoffset = 0;
8401         rsurface.modelelement3s = (unsigned short *)element3s;
8402         rsurface.modelelement3s_indexbuffer = NULL;
8403         rsurface.modelelement3s_bufferoffset = 0;
8404         rsurface.modellightmapoffsets = NULL;
8405         rsurface.modelsurfaces = NULL;
8406         rsurface.batchgeneratedvertex = false;
8407         rsurface.batchfirstvertex = 0;
8408         rsurface.batchnumvertices = 0;
8409         rsurface.batchfirsttriangle = 0;
8410         rsurface.batchnumtriangles = 0;
8411         rsurface.batchvertex3f  = NULL;
8412         rsurface.batchvertex3f_vertexbuffer = NULL;
8413         rsurface.batchvertex3f_bufferoffset = 0;
8414         rsurface.batchsvector3f = NULL;
8415         rsurface.batchsvector3f_vertexbuffer = NULL;
8416         rsurface.batchsvector3f_bufferoffset = 0;
8417         rsurface.batchtvector3f = NULL;
8418         rsurface.batchtvector3f_vertexbuffer = NULL;
8419         rsurface.batchtvector3f_bufferoffset = 0;
8420         rsurface.batchnormal3f  = NULL;
8421         rsurface.batchnormal3f_vertexbuffer = NULL;
8422         rsurface.batchnormal3f_bufferoffset = 0;
8423         rsurface.batchlightmapcolor4f = NULL;
8424         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8425         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8426         rsurface.batchtexcoordtexture2f = NULL;
8427         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8428         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8429         rsurface.batchtexcoordlightmap2f = NULL;
8430         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8431         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8432         rsurface.batchvertexmesh = NULL;
8433         rsurface.batchvertexmeshbuffer = NULL;
8434         rsurface.batchvertex3fbuffer = NULL;
8435         rsurface.batchelement3i = NULL;
8436         rsurface.batchelement3i_indexbuffer = NULL;
8437         rsurface.batchelement3i_bufferoffset = 0;
8438         rsurface.batchelement3s = NULL;
8439         rsurface.batchelement3s_indexbuffer = NULL;
8440         rsurface.batchelement3s_bufferoffset = 0;
8441         rsurface.passcolor4f = NULL;
8442         rsurface.passcolor4f_vertexbuffer = NULL;
8443         rsurface.passcolor4f_bufferoffset = 0;
8444
8445         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8446         {
8447                 if ((wantnormals || wanttangents) && !normal3f)
8448                 {
8449                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8450                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8451                 }
8452                 if (wanttangents && !svector3f)
8453                 {
8454                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8455                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8456                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8457                 }
8458         }
8459 }
8460
8461 float RSurf_FogPoint(const float *v)
8462 {
8463         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8464         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8465         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8466         float FogHeightFade = r_refdef.fogheightfade;
8467         float fogfrac;
8468         unsigned int fogmasktableindex;
8469         if (r_refdef.fogplaneviewabove)
8470                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8471         else
8472                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8473         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8474         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8475 }
8476
8477 float RSurf_FogVertex(const float *v)
8478 {
8479         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8480         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8481         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8482         float FogHeightFade = rsurface.fogheightfade;
8483         float fogfrac;
8484         unsigned int fogmasktableindex;
8485         if (r_refdef.fogplaneviewabove)
8486                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8487         else
8488                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8489         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8490         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8491 }
8492
8493 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8494 {
8495         int i;
8496         for (i = 0;i < numelements;i++)
8497                 outelement3i[i] = inelement3i[i] + adjust;
8498 }
8499
8500 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8501 extern cvar_t gl_vbo;
8502 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8503 {
8504         int deformindex;
8505         int firsttriangle;
8506         int numtriangles;
8507         int firstvertex;
8508         int endvertex;
8509         int numvertices;
8510         int surfacefirsttriangle;
8511         int surfacenumtriangles;
8512         int surfacefirstvertex;
8513         int surfaceendvertex;
8514         int surfacenumvertices;
8515         int batchnumvertices;
8516         int batchnumtriangles;
8517         int needsupdate;
8518         int i, j;
8519         qboolean gaps;
8520         qboolean dynamicvertex;
8521         float amplitude;
8522         float animpos;
8523         float scale;
8524         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8525         float waveparms[4];
8526         q3shaderinfo_deform_t *deform;
8527         const msurface_t *surface, *firstsurface;
8528         r_vertexmesh_t *vertexmesh;
8529         if (!texturenumsurfaces)
8530                 return;
8531         // find vertex range of this surface batch
8532         gaps = false;
8533         firstsurface = texturesurfacelist[0];
8534         firsttriangle = firstsurface->num_firsttriangle;
8535         batchnumvertices = 0;
8536         batchnumtriangles = 0;
8537         firstvertex = endvertex = firstsurface->num_firstvertex;
8538         for (i = 0;i < texturenumsurfaces;i++)
8539         {
8540                 surface = texturesurfacelist[i];
8541                 if (surface != firstsurface + i)
8542                         gaps = true;
8543                 surfacefirstvertex = surface->num_firstvertex;
8544                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8545                 surfacenumvertices = surface->num_vertices;
8546                 surfacenumtriangles = surface->num_triangles;
8547                 if (firstvertex > surfacefirstvertex)
8548                         firstvertex = surfacefirstvertex;
8549                 if (endvertex < surfaceendvertex)
8550                         endvertex = surfaceendvertex;
8551                 batchnumvertices += surfacenumvertices;
8552                 batchnumtriangles += surfacenumtriangles;
8553         }
8554
8555         // we now know the vertex range used, and if there are any gaps in it
8556         rsurface.batchfirstvertex = firstvertex;
8557         rsurface.batchnumvertices = endvertex - firstvertex;
8558         rsurface.batchfirsttriangle = firsttriangle;
8559         rsurface.batchnumtriangles = batchnumtriangles;
8560
8561         // this variable holds flags for which properties have been updated that
8562         // may require regenerating vertexmesh array...
8563         needsupdate = 0;
8564
8565         // check if any dynamic vertex processing must occur
8566         dynamicvertex = false;
8567
8568         // if there is a chance of animated vertex colors, it's a dynamic batch
8569         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8570         {
8571                 dynamicvertex = true;
8572                 batchneed |= BATCHNEED_NOGAPS;
8573                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8574         }
8575
8576         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8577         {
8578                 switch (deform->deform)
8579                 {
8580                 default:
8581                 case Q3DEFORM_PROJECTIONSHADOW:
8582                 case Q3DEFORM_TEXT0:
8583                 case Q3DEFORM_TEXT1:
8584                 case Q3DEFORM_TEXT2:
8585                 case Q3DEFORM_TEXT3:
8586                 case Q3DEFORM_TEXT4:
8587                 case Q3DEFORM_TEXT5:
8588                 case Q3DEFORM_TEXT6:
8589                 case Q3DEFORM_TEXT7:
8590                 case Q3DEFORM_NONE:
8591                         break;
8592                 case Q3DEFORM_AUTOSPRITE:
8593                         dynamicvertex = true;
8594                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8595                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8596                         break;
8597                 case Q3DEFORM_AUTOSPRITE2:
8598                         dynamicvertex = true;
8599                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8600                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8601                         break;
8602                 case Q3DEFORM_NORMAL:
8603                         dynamicvertex = true;
8604                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8605                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8606                         break;
8607                 case Q3DEFORM_WAVE:
8608                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8609                                 break; // if wavefunc is a nop, ignore this transform
8610                         dynamicvertex = true;
8611                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8612                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8613                         break;
8614                 case Q3DEFORM_BULGE:
8615                         dynamicvertex = true;
8616                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8617                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8618                         break;
8619                 case Q3DEFORM_MOVE:
8620                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8621                                 break; // if wavefunc is a nop, ignore this transform
8622                         dynamicvertex = true;
8623                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8624                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8625                         break;
8626                 }
8627         }
8628         switch(rsurface.texture->tcgen.tcgen)
8629         {
8630         default:
8631         case Q3TCGEN_TEXTURE:
8632                 break;
8633         case Q3TCGEN_LIGHTMAP:
8634                 dynamicvertex = true;
8635                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8636                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8637                 break;
8638         case Q3TCGEN_VECTOR:
8639                 dynamicvertex = true;
8640                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8641                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8642                 break;
8643         case Q3TCGEN_ENVIRONMENT:
8644                 dynamicvertex = true;
8645                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8646                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8647                 break;
8648         }
8649         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8650         {
8651                 dynamicvertex = true;
8652                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8653                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8654         }
8655
8656         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8657         {
8658                 dynamicvertex = true;
8659                 batchneed |= BATCHNEED_NOGAPS;
8660                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8661         }
8662
8663         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8664         {
8665                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8666                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8667                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8668                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8669                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8670                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8671                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8672         }
8673
8674         // when the model data has no vertex buffer (dynamic mesh), we need to
8675         // eliminate gaps
8676         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8677                 batchneed |= BATCHNEED_NOGAPS;
8678
8679         // if needsupdate, we have to do a dynamic vertex batch for sure
8680         if (needsupdate & batchneed)
8681                 dynamicvertex = true;
8682
8683         // see if we need to build vertexmesh from arrays
8684         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8685                 dynamicvertex = true;
8686
8687         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8688         // also some drivers strongly dislike firstvertex
8689         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8690                 dynamicvertex = true;
8691
8692         rsurface.batchvertex3f = rsurface.modelvertex3f;
8693         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8694         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8695         rsurface.batchsvector3f = rsurface.modelsvector3f;
8696         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8697         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8698         rsurface.batchtvector3f = rsurface.modeltvector3f;
8699         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8700         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8701         rsurface.batchnormal3f = rsurface.modelnormal3f;
8702         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8703         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8704         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8705         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8706         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8707         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8708         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8709         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8710         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8711         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8712         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8713         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8714         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8715         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8716         rsurface.batchelement3i = rsurface.modelelement3i;
8717         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8718         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8719         rsurface.batchelement3s = rsurface.modelelement3s;
8720         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8721         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8722
8723         // if any dynamic vertex processing has to occur in software, we copy the
8724         // entire surface list together before processing to rebase the vertices
8725         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8726         //
8727         // if any gaps exist and we do not have a static vertex buffer, we have to
8728         // copy the surface list together to avoid wasting upload bandwidth on the
8729         // vertices in the gaps.
8730         //
8731         // if gaps exist and we have a static vertex buffer, we still have to
8732         // combine the index buffer ranges into one dynamic index buffer.
8733         //
8734         // in all cases we end up with data that can be drawn in one call.
8735
8736         if (!dynamicvertex)
8737         {
8738                 // static vertex data, just set pointers...
8739                 rsurface.batchgeneratedvertex = false;
8740                 // if there are gaps, we want to build a combined index buffer,
8741                 // otherwise use the original static buffer with an appropriate offset
8742                 if (gaps)
8743                 {
8744                         // build a new triangle elements array for this batch
8745                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8746                         rsurface.batchfirsttriangle = 0;
8747                         numtriangles = 0;
8748                         for (i = 0;i < texturenumsurfaces;i++)
8749                         {
8750                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8751                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8752                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8753                                 numtriangles += surfacenumtriangles;
8754                         }
8755                         rsurface.batchelement3i_indexbuffer = NULL;
8756                         rsurface.batchelement3i_bufferoffset = 0;
8757                         rsurface.batchelement3s = NULL;
8758                         rsurface.batchelement3s_indexbuffer = NULL;
8759                         rsurface.batchelement3s_bufferoffset = 0;
8760                         if (endvertex <= 65536)
8761                         {
8762                                 // make a 16bit (unsigned short) index array if possible
8763                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8764                                 for (i = 0;i < numtriangles*3;i++)
8765                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8766                         }
8767                 }
8768                 return;
8769         }
8770
8771         // something needs software processing, do it for real...
8772         // we only directly handle separate array data in this case and then
8773         // generate interleaved data if needed...
8774         rsurface.batchgeneratedvertex = true;
8775
8776         // now copy the vertex data into a combined array and make an index array
8777         // (this is what Quake3 does all the time)
8778         //if (gaps || rsurface.batchfirstvertex)
8779         {
8780                 rsurface.batchvertex3fbuffer = NULL;
8781                 rsurface.batchvertexmesh = NULL;
8782                 rsurface.batchvertexmeshbuffer = NULL;
8783                 rsurface.batchvertex3f = NULL;
8784                 rsurface.batchvertex3f_vertexbuffer = NULL;
8785                 rsurface.batchvertex3f_bufferoffset = 0;
8786                 rsurface.batchsvector3f = NULL;
8787                 rsurface.batchsvector3f_vertexbuffer = NULL;
8788                 rsurface.batchsvector3f_bufferoffset = 0;
8789                 rsurface.batchtvector3f = NULL;
8790                 rsurface.batchtvector3f_vertexbuffer = NULL;
8791                 rsurface.batchtvector3f_bufferoffset = 0;
8792                 rsurface.batchnormal3f = NULL;
8793                 rsurface.batchnormal3f_vertexbuffer = NULL;
8794                 rsurface.batchnormal3f_bufferoffset = 0;
8795                 rsurface.batchlightmapcolor4f = NULL;
8796                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8797                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8798                 rsurface.batchtexcoordtexture2f = NULL;
8799                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8800                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8801                 rsurface.batchtexcoordlightmap2f = NULL;
8802                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8803                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8804                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8805                 rsurface.batchelement3i_indexbuffer = NULL;
8806                 rsurface.batchelement3i_bufferoffset = 0;
8807                 rsurface.batchelement3s = NULL;
8808                 rsurface.batchelement3s_indexbuffer = NULL;
8809                 rsurface.batchelement3s_bufferoffset = 0;
8810                 // we'll only be setting up certain arrays as needed
8811                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8812                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8813                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8814                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8815                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8816                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8817                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8818                 {
8819                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8820                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8821                 }
8822                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8823                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8824                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8825                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8826                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8827                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8828                 numvertices = 0;
8829                 numtriangles = 0;
8830                 for (i = 0;i < texturenumsurfaces;i++)
8831                 {
8832                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8833                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8834                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8835                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8836                         // copy only the data requested
8837                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8838                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8839                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8840                         {
8841                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8842                                 {
8843                                         if (rsurface.batchvertex3f)
8844                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8845                                         else
8846                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8847                                 }
8848                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8849                                 {
8850                                         if (rsurface.modelnormal3f)
8851                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8852                                         else
8853                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8854                                 }
8855                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8856                                 {
8857                                         if (rsurface.modelsvector3f)
8858                                         {
8859                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8860                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8861                                         }
8862                                         else
8863                                         {
8864                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8865                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8866                                         }
8867                                 }
8868                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8869                                 {
8870                                         if (rsurface.modellightmapcolor4f)
8871                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8872                                         else
8873                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8874                                 }
8875                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8876                                 {
8877                                         if (rsurface.modeltexcoordtexture2f)
8878                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8879                                         else
8880                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8881                                 }
8882                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8883                                 {
8884                                         if (rsurface.modeltexcoordlightmap2f)
8885                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8886                                         else
8887                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8888                                 }
8889                         }
8890                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8891                         numvertices += surfacenumvertices;
8892                         numtriangles += surfacenumtriangles;
8893                 }
8894
8895                 // generate a 16bit index array as well if possible
8896                 // (in general, dynamic batches fit)
8897                 if (numvertices <= 65536)
8898                 {
8899                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8900                         for (i = 0;i < numtriangles*3;i++)
8901                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8902                 }
8903
8904                 // since we've copied everything, the batch now starts at 0
8905                 rsurface.batchfirstvertex = 0;
8906                 rsurface.batchnumvertices = batchnumvertices;
8907                 rsurface.batchfirsttriangle = 0;
8908                 rsurface.batchnumtriangles = batchnumtriangles;
8909         }
8910
8911         // q1bsp surfaces rendered in vertex color mode have to have colors
8912         // calculated based on lightstyles
8913         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8914         {
8915                 // generate color arrays for the surfaces in this list
8916                 int c[4];
8917                 int scale;
8918                 int size3;
8919                 const int *offsets;
8920                 const unsigned char *lm;
8921                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8922                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8923                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8924                 numvertices = 0;
8925                 for (i = 0;i < texturenumsurfaces;i++)
8926                 {
8927                         surface = texturesurfacelist[i];
8928                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8929                         surfacenumvertices = surface->num_vertices;
8930                         if (surface->lightmapinfo->samples)
8931                         {
8932                                 for (j = 0;j < surfacenumvertices;j++)
8933                                 {
8934                                         lm = surface->lightmapinfo->samples + offsets[j];
8935                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8936                                         VectorScale(lm, scale, c);
8937                                         if (surface->lightmapinfo->styles[1] != 255)
8938                                         {
8939                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8940                                                 lm += size3;
8941                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8942                                                 VectorMA(c, scale, lm, c);
8943                                                 if (surface->lightmapinfo->styles[2] != 255)
8944                                                 {
8945                                                         lm += size3;
8946                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8947                                                         VectorMA(c, scale, lm, c);
8948                                                         if (surface->lightmapinfo->styles[3] != 255)
8949                                                         {
8950                                                                 lm += size3;
8951                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8952                                                                 VectorMA(c, scale, lm, c);
8953                                                         }
8954                                                 }
8955                                         }
8956                                         c[0] >>= 7;
8957                                         c[1] >>= 7;
8958                                         c[2] >>= 7;
8959                                         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);
8960                                         numvertices++;
8961                                 }
8962                         }
8963                         else
8964                         {
8965                                 for (j = 0;j < surfacenumvertices;j++)
8966                                 {
8967                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8968                                         numvertices++;
8969                                 }
8970                         }
8971                 }
8972         }
8973
8974         // if vertices are deformed (sprite flares and things in maps, possibly
8975         // water waves, bulges and other deformations), modify the copied vertices
8976         // in place
8977         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8978         {
8979                 switch (deform->deform)
8980                 {
8981                 default:
8982                 case Q3DEFORM_PROJECTIONSHADOW:
8983                 case Q3DEFORM_TEXT0:
8984                 case Q3DEFORM_TEXT1:
8985                 case Q3DEFORM_TEXT2:
8986                 case Q3DEFORM_TEXT3:
8987                 case Q3DEFORM_TEXT4:
8988                 case Q3DEFORM_TEXT5:
8989                 case Q3DEFORM_TEXT6:
8990                 case Q3DEFORM_TEXT7:
8991                 case Q3DEFORM_NONE:
8992                         break;
8993                 case Q3DEFORM_AUTOSPRITE:
8994                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8995                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8996                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8997                         VectorNormalize(newforward);
8998                         VectorNormalize(newright);
8999                         VectorNormalize(newup);
9000 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9001 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9002 //                      rsurface.batchvertex3f_bufferoffset = 0;
9003 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9004 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9005 //                      rsurface.batchsvector3f_bufferoffset = 0;
9006 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9007 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9008 //                      rsurface.batchtvector3f_bufferoffset = 0;
9009 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9010 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9011 //                      rsurface.batchnormal3f_bufferoffset = 0;
9012                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9013                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9014                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9015                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9016                                 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);
9017                         // a single autosprite surface can contain multiple sprites...
9018                         for (j = 0;j < batchnumvertices - 3;j += 4)
9019                         {
9020                                 VectorClear(center);
9021                                 for (i = 0;i < 4;i++)
9022                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9023                                 VectorScale(center, 0.25f, center);
9024                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9025                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9026                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9027                                 for (i = 0;i < 4;i++)
9028                                 {
9029                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9030                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9031                                 }
9032                         }
9033                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9034                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9035                         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);
9036                         break;
9037                 case Q3DEFORM_AUTOSPRITE2:
9038                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9039                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9040                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9041                         VectorNormalize(newforward);
9042                         VectorNormalize(newright);
9043                         VectorNormalize(newup);
9044 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9045 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9046 //                      rsurface.batchvertex3f_bufferoffset = 0;
9047                         {
9048                                 const float *v1, *v2;
9049                                 vec3_t start, end;
9050                                 float f, l;
9051                                 struct
9052                                 {
9053                                         float length2;
9054                                         const float *v1;
9055                                         const float *v2;
9056                                 }
9057                                 shortest[2];
9058                                 memset(shortest, 0, sizeof(shortest));
9059                                 // a single autosprite surface can contain multiple sprites...
9060                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9061                                 {
9062                                         VectorClear(center);
9063                                         for (i = 0;i < 4;i++)
9064                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9065                                         VectorScale(center, 0.25f, center);
9066                                         // find the two shortest edges, then use them to define the
9067                                         // axis vectors for rotating around the central axis
9068                                         for (i = 0;i < 6;i++)
9069                                         {
9070                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9071                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9072                                                 l = VectorDistance2(v1, v2);
9073                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9074                                                 if (v1[2] != v2[2])
9075                                                         l += (1.0f / 1024.0f);
9076                                                 if (shortest[0].length2 > l || i == 0)
9077                                                 {
9078                                                         shortest[1] = shortest[0];
9079                                                         shortest[0].length2 = l;
9080                                                         shortest[0].v1 = v1;
9081                                                         shortest[0].v2 = v2;
9082                                                 }
9083                                                 else if (shortest[1].length2 > l || i == 1)
9084                                                 {
9085                                                         shortest[1].length2 = l;
9086                                                         shortest[1].v1 = v1;
9087                                                         shortest[1].v2 = v2;
9088                                                 }
9089                                         }
9090                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9091                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9092                                         // this calculates the right vector from the shortest edge
9093                                         // and the up vector from the edge midpoints
9094                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9095                                         VectorNormalize(right);
9096                                         VectorSubtract(end, start, up);
9097                                         VectorNormalize(up);
9098                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9099                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9100                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9101                                         VectorNegate(forward, forward);
9102                                         VectorReflect(forward, 0, up, forward);
9103                                         VectorNormalize(forward);
9104                                         CrossProduct(up, forward, newright);
9105                                         VectorNormalize(newright);
9106                                         // rotate the quad around the up axis vector, this is made
9107                                         // especially easy by the fact we know the quad is flat,
9108                                         // so we only have to subtract the center position and
9109                                         // measure distance along the right vector, and then
9110                                         // multiply that by the newright vector and add back the
9111                                         // center position
9112                                         // we also need to subtract the old position to undo the
9113                                         // displacement from the center, which we do with a
9114                                         // DotProduct, the subtraction/addition of center is also
9115                                         // optimized into DotProducts here
9116                                         l = DotProduct(right, center);
9117                                         for (i = 0;i < 4;i++)
9118                                         {
9119                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9120                                                 f = DotProduct(right, v1) - l;
9121                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9122                                         }
9123                                 }
9124                         }
9125                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9126                         {
9127 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9128 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9129 //                              rsurface.batchnormal3f_bufferoffset = 0;
9130                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9131                         }
9132                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9133                         {
9134 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9135 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9136 //                              rsurface.batchsvector3f_bufferoffset = 0;
9137 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9139 //                              rsurface.batchtvector3f_bufferoffset = 0;
9140                                 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);
9141                         }
9142                         break;
9143                 case Q3DEFORM_NORMAL:
9144                         // deform the normals to make reflections wavey
9145                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9146                         rsurface.batchnormal3f_vertexbuffer = NULL;
9147                         rsurface.batchnormal3f_bufferoffset = 0;
9148                         for (j = 0;j < batchnumvertices;j++)
9149                         {
9150                                 float vertex[3];
9151                                 float *normal = rsurface.batchnormal3f + 3*j;
9152                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9153                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9154                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9155                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9156                                 VectorNormalize(normal);
9157                         }
9158                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9159                         {
9160 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9161 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9162 //                              rsurface.batchsvector3f_bufferoffset = 0;
9163 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9164 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9165 //                              rsurface.batchtvector3f_bufferoffset = 0;
9166                                 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);
9167                         }
9168                         break;
9169                 case Q3DEFORM_WAVE:
9170                         // deform vertex array to make wavey water and flags and such
9171                         waveparms[0] = deform->waveparms[0];
9172                         waveparms[1] = deform->waveparms[1];
9173                         waveparms[2] = deform->waveparms[2];
9174                         waveparms[3] = deform->waveparms[3];
9175                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9176                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9177                         // this is how a divisor of vertex influence on deformation
9178                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9179                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9180 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9181 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9182 //                      rsurface.batchvertex3f_bufferoffset = 0;
9183 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9184 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9185 //                      rsurface.batchnormal3f_bufferoffset = 0;
9186                         for (j = 0;j < batchnumvertices;j++)
9187                         {
9188                                 // if the wavefunc depends on time, evaluate it per-vertex
9189                                 if (waveparms[3])
9190                                 {
9191                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9192                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9193                                 }
9194                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9195                         }
9196                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9197                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9198                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9199                         {
9200 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9201 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9202 //                              rsurface.batchsvector3f_bufferoffset = 0;
9203 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9205 //                              rsurface.batchtvector3f_bufferoffset = 0;
9206                                 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);
9207                         }
9208                         break;
9209                 case Q3DEFORM_BULGE:
9210                         // deform vertex array to make the surface have moving bulges
9211 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9212 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9213 //                      rsurface.batchvertex3f_bufferoffset = 0;
9214 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9215 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9216 //                      rsurface.batchnormal3f_bufferoffset = 0;
9217                         for (j = 0;j < batchnumvertices;j++)
9218                         {
9219                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9220                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9221                         }
9222                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9223                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9224                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9225                         {
9226 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9227 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9228 //                              rsurface.batchsvector3f_bufferoffset = 0;
9229 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9230 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9231 //                              rsurface.batchtvector3f_bufferoffset = 0;
9232                                 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);
9233                         }
9234                         break;
9235                 case Q3DEFORM_MOVE:
9236                         // deform vertex array
9237                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9238                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9239                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9240                         VectorScale(deform->parms, scale, waveparms);
9241 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9243 //                      rsurface.batchvertex3f_bufferoffset = 0;
9244                         for (j = 0;j < batchnumvertices;j++)
9245                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9246                         break;
9247                 }
9248         }
9249
9250         // generate texcoords based on the chosen texcoord source
9251         switch(rsurface.texture->tcgen.tcgen)
9252         {
9253         default:
9254         case Q3TCGEN_TEXTURE:
9255                 break;
9256         case Q3TCGEN_LIGHTMAP:
9257 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9258 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9259 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9260                 if (rsurface.batchtexcoordlightmap2f)
9261                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9262                 break;
9263         case Q3TCGEN_VECTOR:
9264 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9265 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9266 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9267                 for (j = 0;j < batchnumvertices;j++)
9268                 {
9269                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9270                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9271                 }
9272                 break;
9273         case Q3TCGEN_ENVIRONMENT:
9274                 // make environment reflections using a spheremap
9275                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9276                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9277                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9278                 for (j = 0;j < batchnumvertices;j++)
9279                 {
9280                         // identical to Q3A's method, but executed in worldspace so
9281                         // carried models can be shiny too
9282
9283                         float viewer[3], d, reflected[3], worldreflected[3];
9284
9285                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9286                         // VectorNormalize(viewer);
9287
9288                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9289
9290                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9291                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9292                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9293                         // note: this is proportinal to viewer, so we can normalize later
9294
9295                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9296                         VectorNormalize(worldreflected);
9297
9298                         // note: this sphere map only uses world x and z!
9299                         // so positive and negative y will LOOK THE SAME.
9300                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9301                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9302                 }
9303                 break;
9304         }
9305         // the only tcmod that needs software vertex processing is turbulent, so
9306         // check for it here and apply the changes if needed
9307         // and we only support that as the first one
9308         // (handling a mixture of turbulent and other tcmods would be problematic
9309         //  without punting it entirely to a software path)
9310         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9311         {
9312                 amplitude = rsurface.texture->tcmods[0].parms[1];
9313                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9314 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9315 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9316 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9317                 for (j = 0;j < batchnumvertices;j++)
9318                 {
9319                         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);
9320                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9321                 }
9322         }
9323
9324         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9325         {
9326                 // convert the modified arrays to vertex structs
9327 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9328 //              rsurface.batchvertexmeshbuffer = NULL;
9329                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9330                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9331                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9332                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9333                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9334                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9335                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9336                 {
9337                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338                         {
9339                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9340                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9341                         }
9342                 }
9343                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9344                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9345                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9346                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9347                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9348                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9349                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9350                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9351                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9352         }
9353 }
9354
9355 void RSurf_DrawBatch(void)
9356 {
9357         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9358         // through the pipeline, killing it earlier in the pipeline would have
9359         // per-surface overhead rather than per-batch overhead, so it's best to
9360         // reject it here, before it hits glDraw.
9361         if (rsurface.batchnumtriangles == 0)
9362                 return;
9363 #if 0
9364         // batch debugging code
9365         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9366         {
9367                 int i;
9368                 int j;
9369                 int c;
9370                 const int *e;
9371                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9372                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9373                 {
9374                         c = e[i];
9375                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9376                         {
9377                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9378                                 {
9379                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9380                                                 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);
9381                                         break;
9382                                 }
9383                         }
9384                 }
9385         }
9386 #endif
9387         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);
9388 }
9389
9390 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9391 {
9392         // pick the closest matching water plane
9393         int planeindex, vertexindex, bestplaneindex = -1;
9394         float d, bestd;
9395         vec3_t vert;
9396         const float *v;
9397         r_waterstate_waterplane_t *p;
9398         qboolean prepared = false;
9399         bestd = 0;
9400         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9401         {
9402                 if(p->camera_entity != rsurface.texture->camera_entity)
9403                         continue;
9404                 d = 0;
9405                 if(!prepared)
9406                 {
9407                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9408                         prepared = true;
9409                         if(rsurface.batchnumvertices == 0)
9410                                 break;
9411                 }
9412                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9413                 {
9414                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9415                         d += fabs(PlaneDiff(vert, &p->plane));
9416                 }
9417                 if (bestd > d || bestplaneindex < 0)
9418                 {
9419                         bestd = d;
9420                         bestplaneindex = planeindex;
9421                 }
9422         }
9423         return bestplaneindex;
9424         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9425         // this situation though, as it might be better to render single larger
9426         // batches with useless stuff (backface culled for example) than to
9427         // render multiple smaller batches
9428 }
9429
9430 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9431 {
9432         int i;
9433         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9434         rsurface.passcolor4f_vertexbuffer = 0;
9435         rsurface.passcolor4f_bufferoffset = 0;
9436         for (i = 0;i < rsurface.batchnumvertices;i++)
9437                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9438 }
9439
9440 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9441 {
9442         int i;
9443         float f;
9444         const float *v;
9445         const float *c;
9446         float *c2;
9447         if (rsurface.passcolor4f)
9448         {
9449                 // generate color arrays
9450                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9451                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9452                 rsurface.passcolor4f_vertexbuffer = 0;
9453                 rsurface.passcolor4f_bufferoffset = 0;
9454                 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)
9455                 {
9456                         f = RSurf_FogVertex(v);
9457                         c2[0] = c[0] * f;
9458                         c2[1] = c[1] * f;
9459                         c2[2] = c[2] * f;
9460                         c2[3] = c[3];
9461                 }
9462         }
9463         else
9464         {
9465                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9466                 rsurface.passcolor4f_vertexbuffer = 0;
9467                 rsurface.passcolor4f_bufferoffset = 0;
9468                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9469                 {
9470                         f = RSurf_FogVertex(v);
9471                         c2[0] = f;
9472                         c2[1] = f;
9473                         c2[2] = f;
9474                         c2[3] = 1;
9475                 }
9476         }
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9480 {
9481         int i;
9482         float f;
9483         const float *v;
9484         const float *c;
9485         float *c2;
9486         if (!rsurface.passcolor4f)
9487                 return;
9488         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9489         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9490         rsurface.passcolor4f_vertexbuffer = 0;
9491         rsurface.passcolor4f_bufferoffset = 0;
9492         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)
9493         {
9494                 f = RSurf_FogVertex(v);
9495                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9496                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9497                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9498                 c2[3] = c[3];
9499         }
9500 }
9501
9502 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9503 {
9504         int i;
9505         const float *c;
9506         float *c2;
9507         if (!rsurface.passcolor4f)
9508                 return;
9509         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9510         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9511         rsurface.passcolor4f_vertexbuffer = 0;
9512         rsurface.passcolor4f_bufferoffset = 0;
9513         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9514         {
9515                 c2[0] = c[0] * r;
9516                 c2[1] = c[1] * g;
9517                 c2[2] = c[2] * b;
9518                 c2[3] = c[3] * a;
9519         }
9520 }
9521
9522 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9523 {
9524         int i;
9525         const float *c;
9526         float *c2;
9527         if (!rsurface.passcolor4f)
9528                 return;
9529         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9530         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9531         rsurface.passcolor4f_vertexbuffer = 0;
9532         rsurface.passcolor4f_bufferoffset = 0;
9533         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9534         {
9535                 c2[0] = c[0] + r_refdef.scene.ambient;
9536                 c2[1] = c[1] + r_refdef.scene.ambient;
9537                 c2[2] = c[2] + r_refdef.scene.ambient;
9538                 c2[3] = c[3];
9539         }
9540 }
9541
9542 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9543 {
9544         // TODO: optimize
9545         rsurface.passcolor4f = NULL;
9546         rsurface.passcolor4f_vertexbuffer = 0;
9547         rsurface.passcolor4f_bufferoffset = 0;
9548         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9549         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9550         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9551         GL_Color(r, g, b, a);
9552         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9553         RSurf_DrawBatch();
9554 }
9555
9556 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9557 {
9558         // TODO: optimize applyfog && applycolor case
9559         // just apply fog if necessary, and tint the fog color array if necessary
9560         rsurface.passcolor4f = NULL;
9561         rsurface.passcolor4f_vertexbuffer = 0;
9562         rsurface.passcolor4f_bufferoffset = 0;
9563         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9564         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9565         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9566         GL_Color(r, g, b, a);
9567         RSurf_DrawBatch();
9568 }
9569
9570 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9571 {
9572         // TODO: optimize
9573         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9574         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9575         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9576         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9577         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9578         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9579         GL_Color(r, g, b, a);
9580         RSurf_DrawBatch();
9581 }
9582
9583 static void RSurf_DrawBatch_GL11_ClampColor(void)
9584 {
9585         int i;
9586         const float *c1;
9587         float *c2;
9588         if (!rsurface.passcolor4f)
9589                 return;
9590         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9591         {
9592                 c2[0] = bound(0.0f, c1[0], 1.0f);
9593                 c2[1] = bound(0.0f, c1[1], 1.0f);
9594                 c2[2] = bound(0.0f, c1[2], 1.0f);
9595                 c2[3] = bound(0.0f, c1[3], 1.0f);
9596         }
9597 }
9598
9599 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9600 {
9601         int i;
9602         float f;
9603         const float *v;
9604         const float *n;
9605         float *c;
9606         //vec3_t eyedir;
9607
9608         // fake shading
9609         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9610         rsurface.passcolor4f_vertexbuffer = 0;
9611         rsurface.passcolor4f_bufferoffset = 0;
9612         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)
9613         {
9614                 f = -DotProduct(r_refdef.view.forward, n);
9615                 f = max(0, f);
9616                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9617                 f *= r_refdef.lightmapintensity;
9618                 Vector4Set(c, f, f, f, 1);
9619         }
9620 }
9621
9622 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9623 {
9624         RSurf_DrawBatch_GL11_ApplyFakeLight();
9625         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9626         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9627         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9628         GL_Color(r, g, b, a);
9629         RSurf_DrawBatch();
9630 }
9631
9632 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9633 {
9634         int i;
9635         float f;
9636         float alpha;
9637         const float *v;
9638         const float *n;
9639         float *c;
9640         vec3_t ambientcolor;
9641         vec3_t diffusecolor;
9642         vec3_t lightdir;
9643         // TODO: optimize
9644         // model lighting
9645         VectorCopy(rsurface.modellight_lightdir, lightdir);
9646         f = 0.5f * r_refdef.lightmapintensity;
9647         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9648         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9649         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9650         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9651         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9652         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9653         alpha = *a;
9654         if (VectorLength2(diffusecolor) > 0)
9655         {
9656                 // q3-style directional shading
9657                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9658                 rsurface.passcolor4f_vertexbuffer = 0;
9659                 rsurface.passcolor4f_bufferoffset = 0;
9660                 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)
9661                 {
9662                         if ((f = DotProduct(n, lightdir)) > 0)
9663                                 VectorMA(ambientcolor, f, diffusecolor, c);
9664                         else
9665                                 VectorCopy(ambientcolor, c);
9666                         c[3] = alpha;
9667                 }
9668                 *r = 1;
9669                 *g = 1;
9670                 *b = 1;
9671                 *a = 1;
9672                 *applycolor = false;
9673         }
9674         else
9675         {
9676                 *r = ambientcolor[0];
9677                 *g = ambientcolor[1];
9678                 *b = ambientcolor[2];
9679                 rsurface.passcolor4f = NULL;
9680                 rsurface.passcolor4f_vertexbuffer = 0;
9681                 rsurface.passcolor4f_bufferoffset = 0;
9682         }
9683 }
9684
9685 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9686 {
9687         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9688         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9689         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9690         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9691         GL_Color(r, g, b, a);
9692         RSurf_DrawBatch();
9693 }
9694
9695 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9696 {
9697         int i;
9698         float f;
9699         const float *v;
9700         float *c;
9701
9702         // fake shading
9703         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9704         rsurface.passcolor4f_vertexbuffer = 0;
9705         rsurface.passcolor4f_bufferoffset = 0;
9706
9707         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9708         {
9709                 f = 1 - RSurf_FogVertex(v);
9710                 c[0] = r;
9711                 c[1] = g;
9712                 c[2] = b;
9713                 c[3] = f * a;
9714         }
9715 }
9716
9717 void RSurf_SetupDepthAndCulling(void)
9718 {
9719         // submodels are biased to avoid z-fighting with world surfaces that they
9720         // may be exactly overlapping (avoids z-fighting artifacts on certain
9721         // doors and things in Quake maps)
9722         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9723         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9724         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9725         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9726 }
9727
9728 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9729 {
9730         // transparent sky would be ridiculous
9731         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9732                 return;
9733         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9734         skyrenderlater = true;
9735         RSurf_SetupDepthAndCulling();
9736         GL_DepthMask(true);
9737         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9738         // skymasking on them, and Quake3 never did sky masking (unlike
9739         // software Quake and software Quake2), so disable the sky masking
9740         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9741         // and skymasking also looks very bad when noclipping outside the
9742         // level, so don't use it then either.
9743         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9744         {
9745                 R_Mesh_ResetTextureState();
9746                 if (skyrendermasked)
9747                 {
9748                         R_SetupShader_DepthOrShadow(false);
9749                         // depth-only (masking)
9750                         GL_ColorMask(0,0,0,0);
9751                         // just to make sure that braindead drivers don't draw
9752                         // anything despite that colormask...
9753                         GL_BlendFunc(GL_ZERO, GL_ONE);
9754                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9755                         if (rsurface.batchvertex3fbuffer)
9756                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9757                         else
9758                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9759                 }
9760                 else
9761                 {
9762                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9763                         // fog sky
9764                         GL_BlendFunc(GL_ONE, GL_ZERO);
9765                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9766                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9767                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9768                 }
9769                 RSurf_DrawBatch();
9770                 if (skyrendermasked)
9771                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9772         }
9773         R_Mesh_ResetTextureState();
9774         GL_Color(1, 1, 1, 1);
9775 }
9776
9777 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9778 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9779 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9780 {
9781         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9782                 return;
9783         if (prepass)
9784         {
9785                 // render screenspace normalmap to texture
9786                 GL_DepthMask(true);
9787                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9788                 RSurf_DrawBatch();
9789         }
9790
9791         // bind lightmap texture
9792
9793         // water/refraction/reflection/camera surfaces have to be handled specially
9794         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9795         {
9796                 int start, end, startplaneindex;
9797                 for (start = 0;start < texturenumsurfaces;start = end)
9798                 {
9799                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9800                         if(startplaneindex < 0)
9801                         {
9802                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9803                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9804                                 end = start + 1;
9805                                 continue;
9806                         }
9807                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9808                                 ;
9809                         // now that we have a batch using the same planeindex, render it
9810                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9811                         {
9812                                 // render water or distortion background
9813                                 GL_DepthMask(true);
9814                                 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);
9815                                 RSurf_DrawBatch();
9816                                 // blend surface on top
9817                                 GL_DepthMask(false);
9818                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9819                                 RSurf_DrawBatch();
9820                         }
9821                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9822                         {
9823                                 // render surface with reflection texture as input
9824                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9825                                 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);
9826                                 RSurf_DrawBatch();
9827                         }
9828                 }
9829                 return;
9830         }
9831
9832         // render surface batch normally
9833         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9834         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);
9835         RSurf_DrawBatch();
9836 }
9837
9838 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9839 {
9840         // OpenGL 1.3 path - anything not completely ancient
9841         qboolean applycolor;
9842         qboolean applyfog;
9843         int layerindex;
9844         const texturelayer_t *layer;
9845         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);
9846         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9847
9848         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9849         {
9850                 vec4_t layercolor;
9851                 int layertexrgbscale;
9852                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9853                 {
9854                         if (layerindex == 0)
9855                                 GL_AlphaTest(true);
9856                         else
9857                         {
9858                                 GL_AlphaTest(false);
9859                                 GL_DepthFunc(GL_EQUAL);
9860                         }
9861                 }
9862                 GL_DepthMask(layer->depthmask && writedepth);
9863                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9864                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9865                 {
9866                         layertexrgbscale = 4;
9867                         VectorScale(layer->color, 0.25f, layercolor);
9868                 }
9869                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9870                 {
9871                         layertexrgbscale = 2;
9872                         VectorScale(layer->color, 0.5f, layercolor);
9873                 }
9874                 else
9875                 {
9876                         layertexrgbscale = 1;
9877                         VectorScale(layer->color, 1.0f, layercolor);
9878                 }
9879                 layercolor[3] = layer->color[3];
9880                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9881                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9882                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9883                 switch (layer->type)
9884                 {
9885                 case TEXTURELAYERTYPE_LITTEXTURE:
9886                         // single-pass lightmapped texture with 2x rgbscale
9887                         R_Mesh_TexBind(0, r_texture_white);
9888                         R_Mesh_TexMatrix(0, NULL);
9889                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9890                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9891                         R_Mesh_TexBind(1, layer->texture);
9892                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9893                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9894                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9895                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9896                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9897                         else if (FAKELIGHT_ENABLED)
9898                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9899                         else if (rsurface.uselightmaptexture)
9900                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9901                         else
9902                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9903                         break;
9904                 case TEXTURELAYERTYPE_TEXTURE:
9905                         // singletexture unlit texture with transparency support
9906                         R_Mesh_TexBind(0, layer->texture);
9907                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9908                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9909                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9910                         R_Mesh_TexBind(1, 0);
9911                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9912                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9913                         break;
9914                 case TEXTURELAYERTYPE_FOG:
9915                         // singletexture fogging
9916                         if (layer->texture)
9917                         {
9918                                 R_Mesh_TexBind(0, layer->texture);
9919                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9920                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9921                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9922                         }
9923                         else
9924                         {
9925                                 R_Mesh_TexBind(0, 0);
9926                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9927                         }
9928                         R_Mesh_TexBind(1, 0);
9929                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9930                         // generate a color array for the fog pass
9931                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9932                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9933                         RSurf_DrawBatch();
9934                         break;
9935                 default:
9936                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9937                 }
9938         }
9939         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9940         {
9941                 GL_DepthFunc(GL_LEQUAL);
9942                 GL_AlphaTest(false);
9943         }
9944 }
9945
9946 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9947 {
9948         // OpenGL 1.1 - crusty old voodoo path
9949         qboolean applyfog;
9950         int layerindex;
9951         const texturelayer_t *layer;
9952         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);
9953         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9954
9955         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9956         {
9957                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9958                 {
9959                         if (layerindex == 0)
9960                                 GL_AlphaTest(true);
9961                         else
9962                         {
9963                                 GL_AlphaTest(false);
9964                                 GL_DepthFunc(GL_EQUAL);
9965                         }
9966                 }
9967                 GL_DepthMask(layer->depthmask && writedepth);
9968                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9969                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9970                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9971                 switch (layer->type)
9972                 {
9973                 case TEXTURELAYERTYPE_LITTEXTURE:
9974                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9975                         {
9976                                 // two-pass lit texture with 2x rgbscale
9977                                 // first the lightmap pass
9978                                 R_Mesh_TexBind(0, r_texture_white);
9979                                 R_Mesh_TexMatrix(0, NULL);
9980                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9981                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9982                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9983                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9984                                 else if (FAKELIGHT_ENABLED)
9985                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9986                                 else if (rsurface.uselightmaptexture)
9987                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9988                                 else
9989                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9990                                 // then apply the texture to it
9991                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9992                                 R_Mesh_TexBind(0, layer->texture);
9993                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9994                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9995                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9996                                 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);
9997                         }
9998                         else
9999                         {
10000                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10001                                 R_Mesh_TexBind(0, layer->texture);
10002                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10003                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10004                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10005                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10006                                         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);
10007                                 else
10008                                         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);
10009                         }
10010                         break;
10011                 case TEXTURELAYERTYPE_TEXTURE:
10012                         // singletexture unlit texture with transparency support
10013                         R_Mesh_TexBind(0, layer->texture);
10014                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10015                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10016                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10017                         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);
10018                         break;
10019                 case TEXTURELAYERTYPE_FOG:
10020                         // singletexture fogging
10021                         if (layer->texture)
10022                         {
10023                                 R_Mesh_TexBind(0, layer->texture);
10024                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10025                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10026                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10027                         }
10028                         else
10029                         {
10030                                 R_Mesh_TexBind(0, 0);
10031                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10032                         }
10033                         // generate a color array for the fog pass
10034                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10035                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10036                         RSurf_DrawBatch();
10037                         break;
10038                 default:
10039                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10040                 }
10041         }
10042         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10043         {
10044                 GL_DepthFunc(GL_LEQUAL);
10045                 GL_AlphaTest(false);
10046         }
10047 }
10048
10049 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10050 {
10051         int vi;
10052         int j;
10053         r_vertexgeneric_t *batchvertex;
10054         float c[4];
10055
10056 //      R_Mesh_ResetTextureState();
10057         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10058
10059         if(rsurface.texture && rsurface.texture->currentskinframe)
10060         {
10061                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10062                 c[3] *= rsurface.texture->currentalpha;
10063         }
10064         else
10065         {
10066                 c[0] = 1;
10067                 c[1] = 0;
10068                 c[2] = 1;
10069                 c[3] = 1;
10070         }
10071
10072         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10073         {
10074                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10075                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10076                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10077         }
10078
10079         // brighten it up (as texture value 127 means "unlit")
10080         c[0] *= 2 * r_refdef.view.colorscale;
10081         c[1] *= 2 * r_refdef.view.colorscale;
10082         c[2] *= 2 * r_refdef.view.colorscale;
10083
10084         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10085                 c[3] *= r_wateralpha.value;
10086
10087         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10088         {
10089                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10090                 GL_DepthMask(false);
10091         }
10092         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10093         {
10094                 GL_BlendFunc(GL_ONE, GL_ONE);
10095                 GL_DepthMask(false);
10096         }
10097         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10098         {
10099                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10100                 GL_DepthMask(false);
10101         }
10102         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10103         {
10104                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10105                 GL_DepthMask(false);
10106         }
10107         else
10108         {
10109                 GL_BlendFunc(GL_ONE, GL_ZERO);
10110                 GL_DepthMask(writedepth);
10111         }
10112
10113         if (r_showsurfaces.integer == 3)
10114         {
10115                 rsurface.passcolor4f = NULL;
10116
10117                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10118                 {
10119                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10120
10121                         rsurface.passcolor4f = NULL;
10122                         rsurface.passcolor4f_vertexbuffer = 0;
10123                         rsurface.passcolor4f_bufferoffset = 0;
10124                 }
10125                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10126                 {
10127                         qboolean applycolor = true;
10128                         float one = 1.0;
10129
10130                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10131
10132                         r_refdef.lightmapintensity = 1;
10133                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10134                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10135                 }
10136                 else if (FAKELIGHT_ENABLED)
10137                 {
10138                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10139
10140                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10141                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10142                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10143                 }
10144                 else
10145                 {
10146                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10147
10148                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10149                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10150                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10151                 }
10152
10153                 if(!rsurface.passcolor4f)
10154                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10155
10156                 RSurf_DrawBatch_GL11_ApplyAmbient();
10157                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10158                 if(r_refdef.fogenabled)
10159                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10160                 RSurf_DrawBatch_GL11_ClampColor();
10161
10162                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10163                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10164                 RSurf_DrawBatch();
10165         }
10166         else if (!r_refdef.view.showdebug)
10167         {
10168                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10169                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10170                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10171                 {
10172                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10173                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10174                 }
10175                 R_Mesh_PrepareVertices_Generic_Unlock();
10176                 RSurf_DrawBatch();
10177         }
10178         else if (r_showsurfaces.integer == 4)
10179         {
10180                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10182                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10183                 {
10184                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10185                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10186                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10187                 }
10188                 R_Mesh_PrepareVertices_Generic_Unlock();
10189                 RSurf_DrawBatch();
10190         }
10191         else if (r_showsurfaces.integer == 2)
10192         {
10193                 const int *e;
10194                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10195                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10196                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10197                 {
10198                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10199                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10200                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10201                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10202                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10203                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10204                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10205                 }
10206                 R_Mesh_PrepareVertices_Generic_Unlock();
10207                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10208         }
10209         else
10210         {
10211                 int texturesurfaceindex;
10212                 int k;
10213                 const msurface_t *surface;
10214                 float surfacecolor4f[4];
10215                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10216                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10217                 vi = 0;
10218                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10219                 {
10220                         surface = texturesurfacelist[texturesurfaceindex];
10221                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10222                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10223                         for (j = 0;j < surface->num_vertices;j++)
10224                         {
10225                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10226                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10227                                 vi++;
10228                         }
10229                 }
10230                 R_Mesh_PrepareVertices_Generic_Unlock();
10231                 RSurf_DrawBatch();
10232         }
10233 }
10234
10235 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10236 {
10237         CHECKGLERROR
10238         RSurf_SetupDepthAndCulling();
10239         if (r_showsurfaces.integer)
10240         {
10241                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10242                 return;
10243         }
10244         switch (vid.renderpath)
10245         {
10246         case RENDERPATH_GL20:
10247         case RENDERPATH_D3D9:
10248         case RENDERPATH_D3D10:
10249         case RENDERPATH_D3D11:
10250         case RENDERPATH_SOFT:
10251         case RENDERPATH_GLES2:
10252                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10253                 break;
10254         case RENDERPATH_GL13:
10255         case RENDERPATH_GLES1:
10256                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10257                 break;
10258         case RENDERPATH_GL11:
10259                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10260                 break;
10261         }
10262         CHECKGLERROR
10263 }
10264
10265 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10266 {
10267         CHECKGLERROR
10268         RSurf_SetupDepthAndCulling();
10269         if (r_showsurfaces.integer)
10270         {
10271                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10272                 return;
10273         }
10274         switch (vid.renderpath)
10275         {
10276         case RENDERPATH_GL20:
10277         case RENDERPATH_D3D9:
10278         case RENDERPATH_D3D10:
10279         case RENDERPATH_D3D11:
10280         case RENDERPATH_SOFT:
10281         case RENDERPATH_GLES2:
10282                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10283                 break;
10284         case RENDERPATH_GL13:
10285         case RENDERPATH_GLES1:
10286                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10287                 break;
10288         case RENDERPATH_GL11:
10289                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10290                 break;
10291         }
10292         CHECKGLERROR
10293 }
10294
10295 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10296 {
10297         int i, j;
10298         int texturenumsurfaces, endsurface;
10299         texture_t *texture;
10300         const msurface_t *surface;
10301         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10302
10303         // if the model is static it doesn't matter what value we give for
10304         // wantnormals and wanttangents, so this logic uses only rules applicable
10305         // to a model, knowing that they are meaningless otherwise
10306         if (ent == r_refdef.scene.worldentity)
10307                 RSurf_ActiveWorldEntity();
10308         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10309                 RSurf_ActiveModelEntity(ent, false, false, false);
10310         else
10311         {
10312                 switch (vid.renderpath)
10313                 {
10314                 case RENDERPATH_GL20:
10315                 case RENDERPATH_D3D9:
10316                 case RENDERPATH_D3D10:
10317                 case RENDERPATH_D3D11:
10318                 case RENDERPATH_SOFT:
10319                 case RENDERPATH_GLES2:
10320                         RSurf_ActiveModelEntity(ent, true, true, false);
10321                         break;
10322                 case RENDERPATH_GL11:
10323                 case RENDERPATH_GL13:
10324                 case RENDERPATH_GLES1:
10325                         RSurf_ActiveModelEntity(ent, true, false, false);
10326                         break;
10327                 }
10328         }
10329
10330         if (r_transparentdepthmasking.integer)
10331         {
10332                 qboolean setup = false;
10333                 for (i = 0;i < numsurfaces;i = j)
10334                 {
10335                         j = i + 1;
10336                         surface = rsurface.modelsurfaces + surfacelist[i];
10337                         texture = surface->texture;
10338                         rsurface.texture = R_GetCurrentTexture(texture);
10339                         rsurface.lightmaptexture = NULL;
10340                         rsurface.deluxemaptexture = NULL;
10341                         rsurface.uselightmaptexture = false;
10342                         // scan ahead until we find a different texture
10343                         endsurface = min(i + 1024, numsurfaces);
10344                         texturenumsurfaces = 0;
10345                         texturesurfacelist[texturenumsurfaces++] = surface;
10346                         for (;j < endsurface;j++)
10347                         {
10348                                 surface = rsurface.modelsurfaces + surfacelist[j];
10349                                 if (texture != surface->texture)
10350                                         break;
10351                                 texturesurfacelist[texturenumsurfaces++] = surface;
10352                         }
10353                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10354                                 continue;
10355                         // render the range of surfaces as depth
10356                         if (!setup)
10357                         {
10358                                 setup = true;
10359                                 GL_ColorMask(0,0,0,0);
10360                                 GL_Color(1,1,1,1);
10361                                 GL_DepthTest(true);
10362                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10363                                 GL_DepthMask(true);
10364 //                              R_Mesh_ResetTextureState();
10365                                 R_SetupShader_DepthOrShadow(false);
10366                         }
10367                         RSurf_SetupDepthAndCulling();
10368                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10369                         if (rsurface.batchvertex3fbuffer)
10370                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10371                         else
10372                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10373                         RSurf_DrawBatch();
10374                 }
10375                 if (setup)
10376                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10377         }
10378
10379         for (i = 0;i < numsurfaces;i = j)
10380         {
10381                 j = i + 1;
10382                 surface = rsurface.modelsurfaces + surfacelist[i];
10383                 texture = surface->texture;
10384                 rsurface.texture = R_GetCurrentTexture(texture);
10385                 // scan ahead until we find a different texture
10386                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10387                 texturenumsurfaces = 0;
10388                 texturesurfacelist[texturenumsurfaces++] = surface;
10389                 if(FAKELIGHT_ENABLED)
10390                 {
10391                         rsurface.lightmaptexture = NULL;
10392                         rsurface.deluxemaptexture = NULL;
10393                         rsurface.uselightmaptexture = false;
10394                         for (;j < endsurface;j++)
10395                         {
10396                                 surface = rsurface.modelsurfaces + surfacelist[j];
10397                                 if (texture != surface->texture)
10398                                         break;
10399                                 texturesurfacelist[texturenumsurfaces++] = surface;
10400                         }
10401                 }
10402                 else
10403                 {
10404                         rsurface.lightmaptexture = surface->lightmaptexture;
10405                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10406                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10407                         for (;j < endsurface;j++)
10408                         {
10409                                 surface = rsurface.modelsurfaces + surfacelist[j];
10410                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10411                                         break;
10412                                 texturesurfacelist[texturenumsurfaces++] = surface;
10413                         }
10414                 }
10415                 // render the range of surfaces
10416                 if (ent == r_refdef.scene.worldentity)
10417                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10418                 else
10419                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10420         }
10421         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10422 }
10423
10424 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10425 {
10426         // transparent surfaces get pushed off into the transparent queue
10427         int surfacelistindex;
10428         const msurface_t *surface;
10429         vec3_t tempcenter, center;
10430         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10431         {
10432                 surface = texturesurfacelist[surfacelistindex];
10433                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10434                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10435                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10436                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10437                 if (queueentity->transparent_offset) // transparent offset
10438                 {
10439                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10440                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10441                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10442                 }
10443                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10444         }
10445 }
10446
10447 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10448 {
10449         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10450                 return;
10451         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10452                 return;
10453         RSurf_SetupDepthAndCulling();
10454         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10455         if (rsurface.batchvertex3fbuffer)
10456                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10457         else
10458                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10459         RSurf_DrawBatch();
10460 }
10461
10462 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10463 {
10464         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10465         CHECKGLERROR
10466         if (depthonly)
10467                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10468         else if (prepass)
10469         {
10470                 if (!rsurface.texture->currentnumlayers)
10471                         return;
10472                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10473                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10474                 else
10475                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10476         }
10477         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10478                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10479         else if (!rsurface.texture->currentnumlayers)
10480                 return;
10481         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10482         {
10483                 // in the deferred case, transparent surfaces were queued during prepass
10484                 if (!r_shadow_usingdeferredprepass)
10485                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10486         }
10487         else
10488         {
10489                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10490                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10491         }
10492         CHECKGLERROR
10493 }
10494
10495 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10496 {
10497         int i, j;
10498         texture_t *texture;
10499         R_FrameData_SetMark();
10500         // break the surface list down into batches by texture and use of lightmapping
10501         for (i = 0;i < numsurfaces;i = j)
10502         {
10503                 j = i + 1;
10504                 // texture is the base texture pointer, rsurface.texture is the
10505                 // current frame/skin the texture is directing us to use (for example
10506                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10507                 // use skin 1 instead)
10508                 texture = surfacelist[i]->texture;
10509                 rsurface.texture = R_GetCurrentTexture(texture);
10510                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10511                 {
10512                         // if this texture is not the kind we want, skip ahead to the next one
10513                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10514                                 ;
10515                         continue;
10516                 }
10517                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10518                 {
10519                         rsurface.lightmaptexture = NULL;
10520                         rsurface.deluxemaptexture = NULL;
10521                         rsurface.uselightmaptexture = false;
10522                         // simply scan ahead until we find a different texture or lightmap state
10523                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10524                                 ;
10525                 }
10526                 else
10527                 {
10528                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10529                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10530                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10531                         // simply scan ahead until we find a different texture or lightmap state
10532                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10533                                 ;
10534                 }
10535                 // render the range of surfaces
10536                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10537         }
10538         R_FrameData_ReturnToMark();
10539 }
10540
10541 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10542 {
10543         CHECKGLERROR
10544         if (depthonly)
10545                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10546         else if (prepass)
10547         {
10548                 if (!rsurface.texture->currentnumlayers)
10549                         return;
10550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10551                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10552                 else
10553                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10554         }
10555         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10556                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10557         else if (!rsurface.texture->currentnumlayers)
10558                 return;
10559         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10560         {
10561                 // in the deferred case, transparent surfaces were queued during prepass
10562                 if (!r_shadow_usingdeferredprepass)
10563                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10564         }
10565         else
10566         {
10567                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10568                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10569         }
10570         CHECKGLERROR
10571 }
10572
10573 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10574 {
10575         int i, j;
10576         texture_t *texture;
10577         R_FrameData_SetMark();
10578         // break the surface list down into batches by texture and use of lightmapping
10579         for (i = 0;i < numsurfaces;i = j)
10580         {
10581                 j = i + 1;
10582                 // texture is the base texture pointer, rsurface.texture is the
10583                 // current frame/skin the texture is directing us to use (for example
10584                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10585                 // use skin 1 instead)
10586                 texture = surfacelist[i]->texture;
10587                 rsurface.texture = R_GetCurrentTexture(texture);
10588                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10589                 {
10590                         // if this texture is not the kind we want, skip ahead to the next one
10591                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10592                                 ;
10593                         continue;
10594                 }
10595                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10596                 {
10597                         rsurface.lightmaptexture = NULL;
10598                         rsurface.deluxemaptexture = NULL;
10599                         rsurface.uselightmaptexture = false;
10600                         // simply scan ahead until we find a different texture or lightmap state
10601                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10602                                 ;
10603                 }
10604                 else
10605                 {
10606                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10607                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10608                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10609                         // simply scan ahead until we find a different texture or lightmap state
10610                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10611                                 ;
10612                 }
10613                 // render the range of surfaces
10614                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10615         }
10616         R_FrameData_ReturnToMark();
10617 }
10618
10619 float locboxvertex3f[6*4*3] =
10620 {
10621         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10622         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10623         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10624         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10625         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10626         1,0,0, 0,0,0, 0,1,0, 1,1,0
10627 };
10628
10629 unsigned short locboxelements[6*2*3] =
10630 {
10631          0, 1, 2, 0, 2, 3,
10632          4, 5, 6, 4, 6, 7,
10633          8, 9,10, 8,10,11,
10634         12,13,14, 12,14,15,
10635         16,17,18, 16,18,19,
10636         20,21,22, 20,22,23
10637 };
10638
10639 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10640 {
10641         int i, j;
10642         cl_locnode_t *loc = (cl_locnode_t *)ent;
10643         vec3_t mins, size;
10644         float vertex3f[6*4*3];
10645         CHECKGLERROR
10646         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10647         GL_DepthMask(false);
10648         GL_DepthRange(0, 1);
10649         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10650         GL_DepthTest(true);
10651         GL_CullFace(GL_NONE);
10652         R_EntityMatrix(&identitymatrix);
10653
10654 //      R_Mesh_ResetTextureState();
10655
10656         i = surfacelist[0];
10657         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10658                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10659                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10660                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10661
10662         if (VectorCompare(loc->mins, loc->maxs))
10663         {
10664                 VectorSet(size, 2, 2, 2);
10665                 VectorMA(loc->mins, -0.5f, size, mins);
10666         }
10667         else
10668         {
10669                 VectorCopy(loc->mins, mins);
10670                 VectorSubtract(loc->maxs, loc->mins, size);
10671         }
10672
10673         for (i = 0;i < 6*4*3;)
10674                 for (j = 0;j < 3;j++, i++)
10675                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10676
10677         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10678         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10679         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10680 }
10681
10682 void R_DrawLocs(void)
10683 {
10684         int index;
10685         cl_locnode_t *loc, *nearestloc;
10686         vec3_t center;
10687         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10688         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10689         {
10690                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10691                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10692         }
10693 }
10694
10695 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10696 {
10697         if (decalsystem->decals)
10698                 Mem_Free(decalsystem->decals);
10699         memset(decalsystem, 0, sizeof(*decalsystem));
10700 }
10701
10702 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)
10703 {
10704         tridecal_t *decal;
10705         tridecal_t *decals;
10706         int i;
10707
10708         // expand or initialize the system
10709         if (decalsystem->maxdecals <= decalsystem->numdecals)
10710         {
10711                 decalsystem_t old = *decalsystem;
10712                 qboolean useshortelements;
10713                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10714                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10715                 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)));
10716                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10717                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10718                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10719                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10720                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10721                 if (decalsystem->numdecals)
10722                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10723                 if (old.decals)
10724                         Mem_Free(old.decals);
10725                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10726                         decalsystem->element3i[i] = i;
10727                 if (useshortelements)
10728                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10729                                 decalsystem->element3s[i] = i;
10730         }
10731
10732         // grab a decal and search for another free slot for the next one
10733         decals = decalsystem->decals;
10734         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10735         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10736                 ;
10737         decalsystem->freedecal = i;
10738         if (decalsystem->numdecals <= i)
10739                 decalsystem->numdecals = i + 1;
10740
10741         // initialize the decal
10742         decal->lived = 0;
10743         decal->triangleindex = triangleindex;
10744         decal->surfaceindex = surfaceindex;
10745         decal->decalsequence = decalsequence;
10746         decal->color4f[0][0] = c0[0];
10747         decal->color4f[0][1] = c0[1];
10748         decal->color4f[0][2] = c0[2];
10749         decal->color4f[0][3] = 1;
10750         decal->color4f[1][0] = c1[0];
10751         decal->color4f[1][1] = c1[1];
10752         decal->color4f[1][2] = c1[2];
10753         decal->color4f[1][3] = 1;
10754         decal->color4f[2][0] = c2[0];
10755         decal->color4f[2][1] = c2[1];
10756         decal->color4f[2][2] = c2[2];
10757         decal->color4f[2][3] = 1;
10758         decal->vertex3f[0][0] = v0[0];
10759         decal->vertex3f[0][1] = v0[1];
10760         decal->vertex3f[0][2] = v0[2];
10761         decal->vertex3f[1][0] = v1[0];
10762         decal->vertex3f[1][1] = v1[1];
10763         decal->vertex3f[1][2] = v1[2];
10764         decal->vertex3f[2][0] = v2[0];
10765         decal->vertex3f[2][1] = v2[1];
10766         decal->vertex3f[2][2] = v2[2];
10767         decal->texcoord2f[0][0] = t0[0];
10768         decal->texcoord2f[0][1] = t0[1];
10769         decal->texcoord2f[1][0] = t1[0];
10770         decal->texcoord2f[1][1] = t1[1];
10771         decal->texcoord2f[2][0] = t2[0];
10772         decal->texcoord2f[2][1] = t2[1];
10773         TriangleNormal(v0, v1, v2, decal->plane);
10774         VectorNormalize(decal->plane);
10775         decal->plane[3] = DotProduct(v0, decal->plane);
10776 }
10777
10778 extern cvar_t cl_decals_bias;
10779 extern cvar_t cl_decals_models;
10780 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10781 // baseparms, parms, temps
10782 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)
10783 {
10784         int cornerindex;
10785         int index;
10786         float v[9][3];
10787         const float *vertex3f;
10788         const float *normal3f;
10789         int numpoints;
10790         float points[2][9][3];
10791         float temp[3];
10792         float tc[9][2];
10793         float f;
10794         float c[9][4];
10795         const int *e;
10796
10797         e = rsurface.modelelement3i + 3*triangleindex;
10798
10799         vertex3f = rsurface.modelvertex3f;
10800         normal3f = rsurface.modelnormal3f;
10801
10802         if (normal3f)
10803         {
10804                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10805                 {
10806                         index = 3*e[cornerindex];
10807                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10808                 }
10809         }
10810         else
10811         {
10812                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10813                 {
10814                         index = 3*e[cornerindex];
10815                         VectorCopy(vertex3f + index, v[cornerindex]);
10816                 }
10817         }
10818
10819         // cull backfaces
10820         //TriangleNormal(v[0], v[1], v[2], normal);
10821         //if (DotProduct(normal, localnormal) < 0.0f)
10822         //      continue;
10823         // clip by each of the box planes formed from the projection matrix
10824         // if anything survives, we emit the decal
10825         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]);
10826         if (numpoints < 3)
10827                 return;
10828         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]);
10829         if (numpoints < 3)
10830                 return;
10831         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]);
10832         if (numpoints < 3)
10833                 return;
10834         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]);
10835         if (numpoints < 3)
10836                 return;
10837         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]);
10838         if (numpoints < 3)
10839                 return;
10840         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]);
10841         if (numpoints < 3)
10842                 return;
10843         // some part of the triangle survived, so we have to accept it...
10844         if (dynamic)
10845         {
10846                 // dynamic always uses the original triangle
10847                 numpoints = 3;
10848                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10849                 {
10850                         index = 3*e[cornerindex];
10851                         VectorCopy(vertex3f + index, v[cornerindex]);
10852                 }
10853         }
10854         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10855         {
10856                 // convert vertex positions to texcoords
10857                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10858                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10859                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10860                 // calculate distance fade from the projection origin
10861                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10862                 f = bound(0.0f, f, 1.0f);
10863                 c[cornerindex][0] = r * f;
10864                 c[cornerindex][1] = g * f;
10865                 c[cornerindex][2] = b * f;
10866                 c[cornerindex][3] = 1.0f;
10867                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10868         }
10869         if (dynamic)
10870                 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);
10871         else
10872                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10873                         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);
10874 }
10875 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)
10876 {
10877         matrix4x4_t projection;
10878         decalsystem_t *decalsystem;
10879         qboolean dynamic;
10880         dp_model_t *model;
10881         const msurface_t *surface;
10882         const msurface_t *surfaces;
10883         const int *surfacelist;
10884         const texture_t *texture;
10885         int numtriangles;
10886         int numsurfacelist;
10887         int surfacelistindex;
10888         int surfaceindex;
10889         int triangleindex;
10890         float localorigin[3];
10891         float localnormal[3];
10892         float localmins[3];
10893         float localmaxs[3];
10894         float localsize;
10895         //float normal[3];
10896         float planes[6][4];
10897         float angles[3];
10898         bih_t *bih;
10899         int bih_triangles_count;
10900         int bih_triangles[256];
10901         int bih_surfaces[256];
10902
10903         decalsystem = &ent->decalsystem;
10904         model = ent->model;
10905         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10906         {
10907                 R_DecalSystem_Reset(&ent->decalsystem);
10908                 return;
10909         }
10910
10911         if (!model->brush.data_leafs && !cl_decals_models.integer)
10912         {
10913                 if (decalsystem->model)
10914                         R_DecalSystem_Reset(decalsystem);
10915                 return;
10916         }
10917
10918         if (decalsystem->model != model)
10919                 R_DecalSystem_Reset(decalsystem);
10920         decalsystem->model = model;
10921
10922         RSurf_ActiveModelEntity(ent, true, false, false);
10923
10924         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10925         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10926         VectorNormalize(localnormal);
10927         localsize = worldsize*rsurface.inversematrixscale;
10928         localmins[0] = localorigin[0] - localsize;
10929         localmins[1] = localorigin[1] - localsize;
10930         localmins[2] = localorigin[2] - localsize;
10931         localmaxs[0] = localorigin[0] + localsize;
10932         localmaxs[1] = localorigin[1] + localsize;
10933         localmaxs[2] = localorigin[2] + localsize;
10934
10935         //VectorCopy(localnormal, planes[4]);
10936         //VectorVectors(planes[4], planes[2], planes[0]);
10937         AnglesFromVectors(angles, localnormal, NULL, false);
10938         AngleVectors(angles, planes[0], planes[2], planes[4]);
10939         VectorNegate(planes[0], planes[1]);
10940         VectorNegate(planes[2], planes[3]);
10941         VectorNegate(planes[4], planes[5]);
10942         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10943         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10944         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10945         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10946         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10947         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10948
10949 #if 1
10950 // works
10951 {
10952         matrix4x4_t forwardprojection;
10953         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10954         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10955 }
10956 #else
10957 // broken
10958 {
10959         float projectionvector[4][3];
10960         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10961         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10962         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10963         projectionvector[0][0] = planes[0][0] * ilocalsize;
10964         projectionvector[0][1] = planes[1][0] * ilocalsize;
10965         projectionvector[0][2] = planes[2][0] * ilocalsize;
10966         projectionvector[1][0] = planes[0][1] * ilocalsize;
10967         projectionvector[1][1] = planes[1][1] * ilocalsize;
10968         projectionvector[1][2] = planes[2][1] * ilocalsize;
10969         projectionvector[2][0] = planes[0][2] * ilocalsize;
10970         projectionvector[2][1] = planes[1][2] * ilocalsize;
10971         projectionvector[2][2] = planes[2][2] * ilocalsize;
10972         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10973         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10974         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10975         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10976 }
10977 #endif
10978
10979         dynamic = model->surfmesh.isanimated;
10980         numsurfacelist = model->nummodelsurfaces;
10981         surfacelist = model->sortedmodelsurfaces;
10982         surfaces = model->data_surfaces;
10983
10984         bih = NULL;
10985         bih_triangles_count = -1;
10986         if(!dynamic)
10987         {
10988                 if(model->render_bih.numleafs)
10989                         bih = &model->render_bih;
10990                 else if(model->collision_bih.numleafs)
10991                         bih = &model->collision_bih;
10992         }
10993         if(bih)
10994                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10995         if(bih_triangles_count == 0)
10996                 return;
10997         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10998                 return;
10999         if(bih_triangles_count > 0)
11000         {
11001                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11002                 {
11003                         surfaceindex = bih_surfaces[triangleindex];
11004                         surface = surfaces + surfaceindex;
11005                         texture = surface->texture;
11006                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11007                                 continue;
11008                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11009                                 continue;
11010                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11011                 }
11012         }
11013         else
11014         {
11015                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11016                 {
11017                         surfaceindex = surfacelist[surfacelistindex];
11018                         surface = surfaces + surfaceindex;
11019                         // check cull box first because it rejects more than any other check
11020                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11021                                 continue;
11022                         // skip transparent surfaces
11023                         texture = surface->texture;
11024                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11025                                 continue;
11026                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11027                                 continue;
11028                         numtriangles = surface->num_triangles;
11029                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11030                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11031                 }
11032         }
11033 }
11034
11035 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11036 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)
11037 {
11038         int renderentityindex;
11039         float worldmins[3];
11040         float worldmaxs[3];
11041         entity_render_t *ent;
11042
11043         if (!cl_decals_newsystem.integer)
11044                 return;
11045
11046         worldmins[0] = worldorigin[0] - worldsize;
11047         worldmins[1] = worldorigin[1] - worldsize;
11048         worldmins[2] = worldorigin[2] - worldsize;
11049         worldmaxs[0] = worldorigin[0] + worldsize;
11050         worldmaxs[1] = worldorigin[1] + worldsize;
11051         worldmaxs[2] = worldorigin[2] + worldsize;
11052
11053         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11054
11055         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11056         {
11057                 ent = r_refdef.scene.entities[renderentityindex];
11058                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11059                         continue;
11060
11061                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11062         }
11063 }
11064
11065 typedef struct r_decalsystem_splatqueue_s
11066 {
11067         vec3_t worldorigin;
11068         vec3_t worldnormal;
11069         float color[4];
11070         float tcrange[4];
11071         float worldsize;
11072         int decalsequence;
11073 }
11074 r_decalsystem_splatqueue_t;
11075
11076 int r_decalsystem_numqueued = 0;
11077 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11078
11079 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)
11080 {
11081         r_decalsystem_splatqueue_t *queue;
11082
11083         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11084                 return;
11085
11086         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11087         VectorCopy(worldorigin, queue->worldorigin);
11088         VectorCopy(worldnormal, queue->worldnormal);
11089         Vector4Set(queue->color, r, g, b, a);
11090         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11091         queue->worldsize = worldsize;
11092         queue->decalsequence = cl.decalsequence++;
11093 }
11094
11095 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11096 {
11097         int i;
11098         r_decalsystem_splatqueue_t *queue;
11099
11100         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11101                 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);
11102         r_decalsystem_numqueued = 0;
11103 }
11104
11105 extern cvar_t cl_decals_max;
11106 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11107 {
11108         int i;
11109         decalsystem_t *decalsystem = &ent->decalsystem;
11110         int numdecals;
11111         int killsequence;
11112         tridecal_t *decal;
11113         float frametime;
11114         float lifetime;
11115
11116         if (!decalsystem->numdecals)
11117                 return;
11118
11119         if (r_showsurfaces.integer)
11120                 return;
11121
11122         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11123         {
11124                 R_DecalSystem_Reset(decalsystem);
11125                 return;
11126         }
11127
11128         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11129         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11130
11131         if (decalsystem->lastupdatetime)
11132                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11133         else
11134                 frametime = 0;
11135         decalsystem->lastupdatetime = r_refdef.scene.time;
11136         decal = decalsystem->decals;
11137         numdecals = decalsystem->numdecals;
11138
11139         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11140         {
11141                 if (decal->color4f[0][3])
11142                 {
11143                         decal->lived += frametime;
11144                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11145                         {
11146                                 memset(decal, 0, sizeof(*decal));
11147                                 if (decalsystem->freedecal > i)
11148                                         decalsystem->freedecal = i;
11149                         }
11150                 }
11151         }
11152         decal = decalsystem->decals;
11153         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11154                 numdecals--;
11155
11156         // collapse the array by shuffling the tail decals into the gaps
11157         for (;;)
11158         {
11159                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11160                         decalsystem->freedecal++;
11161                 if (decalsystem->freedecal == numdecals)
11162                         break;
11163                 decal[decalsystem->freedecal] = decal[--numdecals];
11164         }
11165
11166         decalsystem->numdecals = numdecals;
11167
11168         if (numdecals <= 0)
11169         {
11170                 // if there are no decals left, reset decalsystem
11171                 R_DecalSystem_Reset(decalsystem);
11172         }
11173 }
11174
11175 extern skinframe_t *decalskinframe;
11176 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11177 {
11178         int i;
11179         decalsystem_t *decalsystem = &ent->decalsystem;
11180         int numdecals;
11181         tridecal_t *decal;
11182         float faderate;
11183         float alpha;
11184         float *v3f;
11185         float *c4f;
11186         float *t2f;
11187         const int *e;
11188         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11189         int numtris = 0;
11190
11191         numdecals = decalsystem->numdecals;
11192         if (!numdecals)
11193                 return;
11194
11195         if (r_showsurfaces.integer)
11196                 return;
11197
11198         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11199         {
11200                 R_DecalSystem_Reset(decalsystem);
11201                 return;
11202         }
11203
11204         // if the model is static it doesn't matter what value we give for
11205         // wantnormals and wanttangents, so this logic uses only rules applicable
11206         // to a model, knowing that they are meaningless otherwise
11207         if (ent == r_refdef.scene.worldentity)
11208                 RSurf_ActiveWorldEntity();
11209         else
11210                 RSurf_ActiveModelEntity(ent, false, false, false);
11211
11212         decalsystem->lastupdatetime = r_refdef.scene.time;
11213         decal = decalsystem->decals;
11214
11215         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11216
11217         // update vertex positions for animated models
11218         v3f = decalsystem->vertex3f;
11219         c4f = decalsystem->color4f;
11220         t2f = decalsystem->texcoord2f;
11221         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11222         {
11223                 if (!decal->color4f[0][3])
11224                         continue;
11225
11226                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11227                         continue;
11228
11229                 // skip backfaces
11230                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11231                         continue;
11232
11233                 // update color values for fading decals
11234                 if (decal->lived >= cl_decals_time.value)
11235                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11236                 else
11237                         alpha = 1.0f;
11238
11239                 c4f[ 0] = decal->color4f[0][0] * alpha;
11240                 c4f[ 1] = decal->color4f[0][1] * alpha;
11241                 c4f[ 2] = decal->color4f[0][2] * alpha;
11242                 c4f[ 3] = 1;
11243                 c4f[ 4] = decal->color4f[1][0] * alpha;
11244                 c4f[ 5] = decal->color4f[1][1] * alpha;
11245                 c4f[ 6] = decal->color4f[1][2] * alpha;
11246                 c4f[ 7] = 1;
11247                 c4f[ 8] = decal->color4f[2][0] * alpha;
11248                 c4f[ 9] = decal->color4f[2][1] * alpha;
11249                 c4f[10] = decal->color4f[2][2] * alpha;
11250                 c4f[11] = 1;
11251
11252                 t2f[0] = decal->texcoord2f[0][0];
11253                 t2f[1] = decal->texcoord2f[0][1];
11254                 t2f[2] = decal->texcoord2f[1][0];
11255                 t2f[3] = decal->texcoord2f[1][1];
11256                 t2f[4] = decal->texcoord2f[2][0];
11257                 t2f[5] = decal->texcoord2f[2][1];
11258
11259                 // update vertex positions for animated models
11260                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11261                 {
11262                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11263                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11264                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11265                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11266                 }
11267                 else
11268                 {
11269                         VectorCopy(decal->vertex3f[0], v3f);
11270                         VectorCopy(decal->vertex3f[1], v3f + 3);
11271                         VectorCopy(decal->vertex3f[2], v3f + 6);
11272                 }
11273
11274                 if (r_refdef.fogenabled)
11275                 {
11276                         alpha = RSurf_FogVertex(v3f);
11277                         VectorScale(c4f, alpha, c4f);
11278                         alpha = RSurf_FogVertex(v3f + 3);
11279                         VectorScale(c4f + 4, alpha, c4f + 4);
11280                         alpha = RSurf_FogVertex(v3f + 6);
11281                         VectorScale(c4f + 8, alpha, c4f + 8);
11282                 }
11283
11284                 v3f += 9;
11285                 c4f += 12;
11286                 t2f += 6;
11287                 numtris++;
11288         }
11289
11290         if (numtris > 0)
11291         {
11292                 r_refdef.stats.drawndecals += numtris;
11293
11294                 // now render the decals all at once
11295                 // (this assumes they all use one particle font texture!)
11296                 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);
11297 //              R_Mesh_ResetTextureState();
11298                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11299                 GL_DepthMask(false);
11300                 GL_DepthRange(0, 1);
11301                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11302                 GL_DepthTest(true);
11303                 GL_CullFace(GL_NONE);
11304                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11305                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11306                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11307         }
11308 }
11309
11310 static void R_DrawModelDecals(void)
11311 {
11312         int i, numdecals;
11313
11314         // fade faster when there are too many decals
11315         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11316         for (i = 0;i < r_refdef.scene.numentities;i++)
11317                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11318
11319         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11320         for (i = 0;i < r_refdef.scene.numentities;i++)
11321                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11322                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11323
11324         R_DecalSystem_ApplySplatEntitiesQueue();
11325
11326         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11327         for (i = 0;i < r_refdef.scene.numentities;i++)
11328                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11329
11330         r_refdef.stats.totaldecals += numdecals;
11331
11332         if (r_showsurfaces.integer)
11333                 return;
11334
11335         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11336
11337         for (i = 0;i < r_refdef.scene.numentities;i++)
11338         {
11339                 if (!r_refdef.viewcache.entityvisible[i])
11340                         continue;
11341                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11342                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11343         }
11344 }
11345
11346 extern cvar_t mod_collision_bih;
11347 void R_DrawDebugModel(void)
11348 {
11349         entity_render_t *ent = rsurface.entity;
11350         int i, j, k, l, flagsmask;
11351         const msurface_t *surface;
11352         dp_model_t *model = ent->model;
11353         vec3_t v;
11354
11355         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11356                 return;
11357
11358         if (r_showoverdraw.value > 0)
11359         {
11360                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11361                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11362                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11363                 GL_DepthTest(false);
11364                 GL_DepthMask(false);
11365                 GL_DepthRange(0, 1);
11366                 GL_BlendFunc(GL_ONE, GL_ONE);
11367                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11368                 {
11369                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11370                                 continue;
11371                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11372                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11373                         {
11374                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11375                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11376                                 if (!rsurface.texture->currentlayers->depthmask)
11377                                         GL_Color(c, 0, 0, 1.0f);
11378                                 else if (ent == r_refdef.scene.worldentity)
11379                                         GL_Color(c, c, c, 1.0f);
11380                                 else
11381                                         GL_Color(0, c, 0, 1.0f);
11382                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11383                                 RSurf_DrawBatch();
11384                         }
11385                 }
11386                 rsurface.texture = NULL;
11387         }
11388
11389         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11390
11391 //      R_Mesh_ResetTextureState();
11392         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11393         GL_DepthRange(0, 1);
11394         GL_DepthTest(!r_showdisabledepthtest.integer);
11395         GL_DepthMask(false);
11396         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11397
11398         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11399         {
11400                 int triangleindex;
11401                 int bihleafindex;
11402                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11403                 const q3mbrush_t *brush;
11404                 const bih_t *bih = &model->collision_bih;
11405                 const bih_leaf_t *bihleaf;
11406                 float vertex3f[3][3];
11407                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11408                 cullbox = false;
11409                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11410                 {
11411                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11412                                 continue;
11413                         switch (bihleaf->type)
11414                         {
11415                         case BIH_BRUSH:
11416                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11417                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11418                                 {
11419                                         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);
11420                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11421                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11422                                 }
11423                                 break;
11424                         case BIH_COLLISIONTRIANGLE:
11425                                 triangleindex = bihleaf->itemindex;
11426                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11427                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11428                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11429                                 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);
11430                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11431                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11432                                 break;
11433                         case BIH_RENDERTRIANGLE:
11434                                 triangleindex = bihleaf->itemindex;
11435                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11436                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11437                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11438                                 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);
11439                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11440                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11441                                 break;
11442                         }
11443                 }
11444         }
11445
11446         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11447
11448 #ifndef USE_GLES2
11449         if (r_showtris.integer && qglPolygonMode)
11450         {
11451                 if (r_showdisabledepthtest.integer)
11452                 {
11453                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11454                         GL_DepthMask(false);
11455                 }
11456                 else
11457                 {
11458                         GL_BlendFunc(GL_ONE, GL_ZERO);
11459                         GL_DepthMask(true);
11460                 }
11461                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11462                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11463                 {
11464                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11465                                 continue;
11466                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11467                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11468                         {
11469                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11470                                 if (!rsurface.texture->currentlayers->depthmask)
11471                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11472                                 else if (ent == r_refdef.scene.worldentity)
11473                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11474                                 else
11475                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11476                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11477                                 RSurf_DrawBatch();
11478                         }
11479                 }
11480                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11481                 rsurface.texture = NULL;
11482         }
11483
11484         if (r_shownormals.value != 0 && qglBegin)
11485         {
11486                 if (r_showdisabledepthtest.integer)
11487                 {
11488                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11489                         GL_DepthMask(false);
11490                 }
11491                 else
11492                 {
11493                         GL_BlendFunc(GL_ONE, GL_ZERO);
11494                         GL_DepthMask(true);
11495                 }
11496                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11497                 {
11498                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11499                                 continue;
11500                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11501                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11502                         {
11503                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11504                                 qglBegin(GL_LINES);
11505                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11506                                 {
11507                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11508                                         {
11509                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11510                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11511                                                 qglVertex3f(v[0], v[1], v[2]);
11512                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11513                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11514                                                 qglVertex3f(v[0], v[1], v[2]);
11515                                         }
11516                                 }
11517                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11518                                 {
11519                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11520                                         {
11521                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11522                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11523                                                 qglVertex3f(v[0], v[1], v[2]);
11524                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11525                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11526                                                 qglVertex3f(v[0], v[1], v[2]);
11527                                         }
11528                                 }
11529                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11530                                 {
11531                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11532                                         {
11533                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11534                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11535                                                 qglVertex3f(v[0], v[1], v[2]);
11536                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11537                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11538                                                 qglVertex3f(v[0], v[1], v[2]);
11539                                         }
11540                                 }
11541                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11542                                 {
11543                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11544                                         {
11545                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11546                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11547                                                 qglVertex3f(v[0], v[1], v[2]);
11548                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11549                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11550                                                 qglVertex3f(v[0], v[1], v[2]);
11551                                         }
11552                                 }
11553                                 qglEnd();
11554                                 CHECKGLERROR
11555                         }
11556                 }
11557                 rsurface.texture = NULL;
11558         }
11559 #endif
11560 }
11561
11562 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11563 int r_maxsurfacelist = 0;
11564 const msurface_t **r_surfacelist = NULL;
11565 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11566 {
11567         int i, j, endj, flagsmask;
11568         dp_model_t *model = r_refdef.scene.worldmodel;
11569         msurface_t *surfaces;
11570         unsigned char *update;
11571         int numsurfacelist = 0;
11572         if (model == NULL)
11573                 return;
11574
11575         if (r_maxsurfacelist < model->num_surfaces)
11576         {
11577                 r_maxsurfacelist = model->num_surfaces;
11578                 if (r_surfacelist)
11579                         Mem_Free((msurface_t**)r_surfacelist);
11580                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11581         }
11582
11583         RSurf_ActiveWorldEntity();
11584
11585         surfaces = model->data_surfaces;
11586         update = model->brushq1.lightmapupdateflags;
11587
11588         // update light styles on this submodel
11589         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11590         {
11591                 model_brush_lightstyleinfo_t *style;
11592                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11593                 {
11594                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11595                         {
11596                                 int *list = style->surfacelist;
11597                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11598                                 for (j = 0;j < style->numsurfaces;j++)
11599                                         update[list[j]] = true;
11600                         }
11601                 }
11602         }
11603
11604         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11605
11606         if (debug)
11607         {
11608                 R_DrawDebugModel();
11609                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11610                 return;
11611         }
11612
11613         rsurface.lightmaptexture = NULL;
11614         rsurface.deluxemaptexture = NULL;
11615         rsurface.uselightmaptexture = false;
11616         rsurface.texture = NULL;
11617         rsurface.rtlight = NULL;
11618         numsurfacelist = 0;
11619         // add visible surfaces to draw list
11620         for (i = 0;i < model->nummodelsurfaces;i++)
11621         {
11622                 j = model->sortedmodelsurfaces[i];
11623                 if (r_refdef.viewcache.world_surfacevisible[j])
11624                         r_surfacelist[numsurfacelist++] = surfaces + j;
11625         }
11626         // update lightmaps if needed
11627         if (model->brushq1.firstrender)
11628         {
11629                 model->brushq1.firstrender = false;
11630                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11631                         if (update[j])
11632                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11633         }
11634         else if (update)
11635         {
11636                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11637                         if (r_refdef.viewcache.world_surfacevisible[j])
11638                                 if (update[j])
11639                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11640         }
11641         // don't do anything if there were no surfaces
11642         if (!numsurfacelist)
11643         {
11644                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11645                 return;
11646         }
11647         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11648
11649         // add to stats if desired
11650         if (r_speeds.integer && !skysurfaces && !depthonly)
11651         {
11652                 r_refdef.stats.world_surfaces += numsurfacelist;
11653                 for (j = 0;j < numsurfacelist;j++)
11654                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11655         }
11656
11657         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11658 }
11659
11660 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11661 {
11662         int i, j, endj, flagsmask;
11663         dp_model_t *model = ent->model;
11664         msurface_t *surfaces;
11665         unsigned char *update;
11666         int numsurfacelist = 0;
11667         if (model == NULL)
11668                 return;
11669
11670         if (r_maxsurfacelist < model->num_surfaces)
11671         {
11672                 r_maxsurfacelist = model->num_surfaces;
11673                 if (r_surfacelist)
11674                         Mem_Free((msurface_t **)r_surfacelist);
11675                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11676         }
11677
11678         // if the model is static it doesn't matter what value we give for
11679         // wantnormals and wanttangents, so this logic uses only rules applicable
11680         // to a model, knowing that they are meaningless otherwise
11681         if (ent == r_refdef.scene.worldentity)
11682                 RSurf_ActiveWorldEntity();
11683         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11684                 RSurf_ActiveModelEntity(ent, false, false, false);
11685         else if (prepass)
11686                 RSurf_ActiveModelEntity(ent, true, true, true);
11687         else if (depthonly)
11688         {
11689                 switch (vid.renderpath)
11690                 {
11691                 case RENDERPATH_GL20:
11692                 case RENDERPATH_D3D9:
11693                 case RENDERPATH_D3D10:
11694                 case RENDERPATH_D3D11:
11695                 case RENDERPATH_SOFT:
11696                 case RENDERPATH_GLES2:
11697                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11698                         break;
11699                 case RENDERPATH_GL11:
11700                 case RENDERPATH_GL13:
11701                 case RENDERPATH_GLES1:
11702                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11703                         break;
11704                 }
11705         }
11706         else
11707         {
11708                 switch (vid.renderpath)
11709                 {
11710                 case RENDERPATH_GL20:
11711                 case RENDERPATH_D3D9:
11712                 case RENDERPATH_D3D10:
11713                 case RENDERPATH_D3D11:
11714                 case RENDERPATH_SOFT:
11715                 case RENDERPATH_GLES2:
11716                         RSurf_ActiveModelEntity(ent, true, true, false);
11717                         break;
11718                 case RENDERPATH_GL11:
11719                 case RENDERPATH_GL13:
11720                 case RENDERPATH_GLES1:
11721                         RSurf_ActiveModelEntity(ent, true, false, false);
11722                         break;
11723                 }
11724         }
11725
11726         surfaces = model->data_surfaces;
11727         update = model->brushq1.lightmapupdateflags;
11728
11729         // update light styles
11730         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11731         {
11732                 model_brush_lightstyleinfo_t *style;
11733                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11734                 {
11735                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11736                         {
11737                                 int *list = style->surfacelist;
11738                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11739                                 for (j = 0;j < style->numsurfaces;j++)
11740                                         update[list[j]] = true;
11741                         }
11742                 }
11743         }
11744
11745         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11746
11747         if (debug)
11748         {
11749                 R_DrawDebugModel();
11750                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11751                 return;
11752         }
11753
11754         rsurface.lightmaptexture = NULL;
11755         rsurface.deluxemaptexture = NULL;
11756         rsurface.uselightmaptexture = false;
11757         rsurface.texture = NULL;
11758         rsurface.rtlight = NULL;
11759         numsurfacelist = 0;
11760         // add visible surfaces to draw list
11761         for (i = 0;i < model->nummodelsurfaces;i++)
11762                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11763         // don't do anything if there were no surfaces
11764         if (!numsurfacelist)
11765         {
11766                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11767                 return;
11768         }
11769         // update lightmaps if needed
11770         if (update)
11771         {
11772                 int updated = 0;
11773                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11774                 {
11775                         if (update[j])
11776                         {
11777                                 updated++;
11778                                 R_BuildLightMap(ent, surfaces + j);
11779                         }
11780                 }
11781         }
11782         if (update)
11783                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11784                         if (update[j])
11785                                 R_BuildLightMap(ent, surfaces + j);
11786         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11787
11788         // add to stats if desired
11789         if (r_speeds.integer && !skysurfaces && !depthonly)
11790         {
11791                 r_refdef.stats.entities_surfaces += numsurfacelist;
11792                 for (j = 0;j < numsurfacelist;j++)
11793                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11794         }
11795
11796         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11797 }
11798
11799 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11800 {
11801         static texture_t texture;
11802         static msurface_t surface;
11803         const msurface_t *surfacelist = &surface;
11804
11805         // fake enough texture and surface state to render this geometry
11806
11807         texture.update_lastrenderframe = -1; // regenerate this texture
11808         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11809         texture.currentskinframe = skinframe;
11810         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11811         texture.offsetmapping = OFFSETMAPPING_OFF;
11812         texture.offsetscale = 1;
11813         texture.specularscalemod = 1;
11814         texture.specularpowermod = 1;
11815
11816         surface.texture = &texture;
11817         surface.num_triangles = numtriangles;
11818         surface.num_firsttriangle = firsttriangle;
11819         surface.num_vertices = numvertices;
11820         surface.num_firstvertex = firstvertex;
11821
11822         // now render it
11823         rsurface.texture = R_GetCurrentTexture(surface.texture);
11824         rsurface.lightmaptexture = NULL;
11825         rsurface.deluxemaptexture = NULL;
11826         rsurface.uselightmaptexture = false;
11827         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11828 }
11829
11830 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)
11831 {
11832         static msurface_t surface;
11833         const msurface_t *surfacelist = &surface;
11834
11835         // fake enough texture and surface state to render this geometry
11836         surface.texture = texture;
11837         surface.num_triangles = numtriangles;
11838         surface.num_firsttriangle = firsttriangle;
11839         surface.num_vertices = numvertices;
11840         surface.num_firstvertex = firstvertex;
11841
11842         // now render it
11843         rsurface.texture = R_GetCurrentTexture(surface.texture);
11844         rsurface.lightmaptexture = NULL;
11845         rsurface.deluxemaptexture = NULL;
11846         rsurface.uselightmaptexture = false;
11847         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11848 }