]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix bugs introduced by r11262
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
144 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
151 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
152 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
153 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
154 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
155 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
156 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
157 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
158
159 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
160 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
161 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
164 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
165 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
166 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
167 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
168 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
169 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
173 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
174 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
175 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
176 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
177
178 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
179 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
180 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
181 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
182 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
183 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
184 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
185
186 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
187 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
188 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
189 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
190
191 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
192 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
193 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
194 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
195 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
196 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
197 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
198
199 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
200 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
203 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
204 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
205 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
208 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
209 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
210
211 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
212
213 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
214
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
216
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
218
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
221
222 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
223
224 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
225
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
228
229 extern qboolean v_flipped_state;
230
231 static struct r_bloomstate_s
232 {
233         qboolean enabled;
234         qboolean hdr;
235
236         int bloomwidth, bloomheight;
237
238         textype_t texturetype;
239         int viewfbo; // used to check if r_viewfbo cvar has changed
240
241         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
242         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
243         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
244
245         int screentexturewidth, screentextureheight;
246         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
247
248         int bloomtexturewidth, bloomtextureheight;
249         rtexture_t *texture_bloom;
250
251         // arrays for rendering the screen passes
252         float screentexcoord2f[8];
253         float bloomtexcoord2f[8];
254         float offsettexcoord2f[8];
255
256         r_viewport_t viewport;
257 }
258 r_bloomstate;
259
260 r_waterstate_t r_waterstate;
261
262 /// shadow volume bsp struct with automatically growing nodes buffer
263 svbsp_t r_svbsp;
264
265 rtexture_t *r_texture_blanknormalmap;
266 rtexture_t *r_texture_white;
267 rtexture_t *r_texture_grey128;
268 rtexture_t *r_texture_black;
269 rtexture_t *r_texture_notexture;
270 rtexture_t *r_texture_whitecube;
271 rtexture_t *r_texture_normalizationcube;
272 rtexture_t *r_texture_fogattenuation;
273 rtexture_t *r_texture_fogheighttexture;
274 rtexture_t *r_texture_gammaramps;
275 unsigned int r_texture_gammaramps_serial;
276 //rtexture_t *r_texture_fogintensity;
277 rtexture_t *r_texture_reflectcube;
278
279 // TODO: hash lookups?
280 typedef struct cubemapinfo_s
281 {
282         char basename[64];
283         rtexture_t *texture;
284 }
285 cubemapinfo_t;
286
287 int r_texture_numcubemaps;
288 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
289
290 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
291 unsigned int r_numqueries;
292 unsigned int r_maxqueries;
293
294 typedef struct r_qwskincache_s
295 {
296         char name[MAX_QPATH];
297         skinframe_t *skinframe;
298 }
299 r_qwskincache_t;
300
301 static r_qwskincache_t *r_qwskincache;
302 static int r_qwskincache_size;
303
304 /// vertex coordinates for a quad that covers the screen exactly
305 extern const float r_screenvertex3f[12];
306 extern const float r_d3dscreenvertex3f[12];
307 const float r_screenvertex3f[12] =
308 {
309         0, 0, 0,
310         1, 0, 0,
311         1, 1, 0,
312         0, 1, 0
313 };
314 const float r_d3dscreenvertex3f[12] =
315 {
316         0, 1, 0,
317         1, 1, 0,
318         1, 0, 0,
319         0, 0, 0
320 };
321
322 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
323 {
324         int i;
325         for (i = 0;i < verts;i++)
326         {
327                 out[0] = in[0] * r;
328                 out[1] = in[1] * g;
329                 out[2] = in[2] * b;
330                 out[3] = in[3];
331                 in += 4;
332                 out += 4;
333         }
334 }
335
336 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
337 {
338         int i;
339         for (i = 0;i < verts;i++)
340         {
341                 out[0] = r;
342                 out[1] = g;
343                 out[2] = b;
344                 out[3] = a;
345                 out += 4;
346         }
347 }
348
349 // FIXME: move this to client?
350 void FOG_clear(void)
351 {
352         if (gamemode == GAME_NEHAHRA)
353         {
354                 Cvar_Set("gl_fogenable", "0");
355                 Cvar_Set("gl_fogdensity", "0.2");
356                 Cvar_Set("gl_fogred", "0.3");
357                 Cvar_Set("gl_foggreen", "0.3");
358                 Cvar_Set("gl_fogblue", "0.3");
359         }
360         r_refdef.fog_density = 0;
361         r_refdef.fog_red = 0;
362         r_refdef.fog_green = 0;
363         r_refdef.fog_blue = 0;
364         r_refdef.fog_alpha = 1;
365         r_refdef.fog_start = 0;
366         r_refdef.fog_end = 16384;
367         r_refdef.fog_height = 1<<30;
368         r_refdef.fog_fadedepth = 128;
369         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
370 }
371
372 static void R_BuildBlankTextures(void)
373 {
374         unsigned char data[4];
375         data[2] = 128; // normal X
376         data[1] = 128; // normal Y
377         data[0] = 255; // normal Z
378         data[3] = 128; // height
379         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 255;
381         data[1] = 255;
382         data[2] = 255;
383         data[3] = 255;
384         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 128;
386         data[1] = 128;
387         data[2] = 128;
388         data[3] = 255;
389         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390         data[0] = 0;
391         data[1] = 0;
392         data[2] = 0;
393         data[3] = 255;
394         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
395 }
396
397 static void R_BuildNoTexture(void)
398 {
399         int x, y;
400         unsigned char pix[16][16][4];
401         // this makes a light grey/dark grey checkerboard texture
402         for (y = 0;y < 16;y++)
403         {
404                 for (x = 0;x < 16;x++)
405                 {
406                         if ((y < 8) ^ (x < 8))
407                         {
408                                 pix[y][x][0] = 128;
409                                 pix[y][x][1] = 128;
410                                 pix[y][x][2] = 128;
411                                 pix[y][x][3] = 255;
412                         }
413                         else
414                         {
415                                 pix[y][x][0] = 64;
416                                 pix[y][x][1] = 64;
417                                 pix[y][x][2] = 64;
418                                 pix[y][x][3] = 255;
419                         }
420                 }
421         }
422         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
423 }
424
425 static void R_BuildWhiteCube(void)
426 {
427         unsigned char data[6*1*1*4];
428         memset(data, 255, sizeof(data));
429         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
430 }
431
432 static void R_BuildNormalizationCube(void)
433 {
434         int x, y, side;
435         vec3_t v;
436         vec_t s, t, intensity;
437 #define NORMSIZE 64
438         unsigned char *data;
439         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
440         for (side = 0;side < 6;side++)
441         {
442                 for (y = 0;y < NORMSIZE;y++)
443                 {
444                         for (x = 0;x < NORMSIZE;x++)
445                         {
446                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
447                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
448                                 switch(side)
449                                 {
450                                 default:
451                                 case 0:
452                                         v[0] = 1;
453                                         v[1] = -t;
454                                         v[2] = -s;
455                                         break;
456                                 case 1:
457                                         v[0] = -1;
458                                         v[1] = -t;
459                                         v[2] = s;
460                                         break;
461                                 case 2:
462                                         v[0] = s;
463                                         v[1] = 1;
464                                         v[2] = t;
465                                         break;
466                                 case 3:
467                                         v[0] = s;
468                                         v[1] = -1;
469                                         v[2] = -t;
470                                         break;
471                                 case 4:
472                                         v[0] = s;
473                                         v[1] = -t;
474                                         v[2] = 1;
475                                         break;
476                                 case 5:
477                                         v[0] = -s;
478                                         v[1] = -t;
479                                         v[2] = -1;
480                                         break;
481                                 }
482                                 intensity = 127.0f / sqrt(DotProduct(v, v));
483                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
484                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
485                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
486                                 data[((side*64+y)*64+x)*4+3] = 255;
487                         }
488                 }
489         }
490         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
491         Mem_Free(data);
492 }
493
494 static void R_BuildFogTexture(void)
495 {
496         int x, b;
497 #define FOGWIDTH 256
498         unsigned char data1[FOGWIDTH][4];
499         //unsigned char data2[FOGWIDTH][4];
500         double d, r, alpha;
501
502         r_refdef.fogmasktable_start = r_refdef.fog_start;
503         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
504         r_refdef.fogmasktable_range = r_refdef.fogrange;
505         r_refdef.fogmasktable_density = r_refdef.fog_density;
506
507         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
508         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
509         {
510                 d = (x * r - r_refdef.fogmasktable_start);
511                 if(developer_extra.integer)
512                         Con_DPrintf("%f ", d);
513                 d = max(0, d);
514                 if (r_fog_exp2.integer)
515                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
516                 else
517                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
518                 if(developer_extra.integer)
519                         Con_DPrintf(" : %f ", alpha);
520                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
521                 if(developer_extra.integer)
522                         Con_DPrintf(" = %f\n", alpha);
523                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
524         }
525
526         for (x = 0;x < FOGWIDTH;x++)
527         {
528                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
529                 data1[x][0] = b;
530                 data1[x][1] = b;
531                 data1[x][2] = b;
532                 data1[x][3] = 255;
533                 //data2[x][0] = 255 - b;
534                 //data2[x][1] = 255 - b;
535                 //data2[x][2] = 255 - b;
536                 //data2[x][3] = 255;
537         }
538         if (r_texture_fogattenuation)
539         {
540                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
541                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
542         }
543         else
544         {
545                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
546                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
547         }
548 }
549
550 static void R_BuildFogHeightTexture(void)
551 {
552         unsigned char *inpixels;
553         int size;
554         int x;
555         int y;
556         int j;
557         float c[4];
558         float f;
559         inpixels = NULL;
560         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
561         if (r_refdef.fogheighttexturename[0])
562                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
563         if (!inpixels)
564         {
565                 r_refdef.fog_height_tablesize = 0;
566                 if (r_texture_fogheighttexture)
567                         R_FreeTexture(r_texture_fogheighttexture);
568                 r_texture_fogheighttexture = NULL;
569                 if (r_refdef.fog_height_table2d)
570                         Mem_Free(r_refdef.fog_height_table2d);
571                 r_refdef.fog_height_table2d = NULL;
572                 if (r_refdef.fog_height_table1d)
573                         Mem_Free(r_refdef.fog_height_table1d);
574                 r_refdef.fog_height_table1d = NULL;
575                 return;
576         }
577         size = image_width;
578         r_refdef.fog_height_tablesize = size;
579         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
580         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
581         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
582         Mem_Free(inpixels);
583         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
584         // average fog color table accounting for every fog layer between a point
585         // and the camera.  (Note: attenuation is handled separately!)
586         for (y = 0;y < size;y++)
587         {
588                 for (x = 0;x < size;x++)
589                 {
590                         Vector4Clear(c);
591                         f = 0;
592                         if (x < y)
593                         {
594                                 for (j = x;j <= y;j++)
595                                 {
596                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
597                                         f++;
598                                 }
599                         }
600                         else
601                         {
602                                 for (j = x;j >= y;j--)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         f = 1.0f / f;
609                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
610                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
611                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
613                 }
614         }
615         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
616 }
617
618 //=======================================================================================================================================================
619
620 static const char *builtinshaderstring =
621 #include "shader_glsl.h"
622 ;
623
624 const char *builtinhlslshaderstring =
625 #include "shader_hlsl.h"
626 ;
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *vertexfilename;
643         const char *geometryfilename;
644         const char *fragmentfilename;
645         const char *pretext;
646         const char *name;
647 }
648 shadermodeinfo_t;
649
650 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
651 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
652 {
653         {"#define USEDIFFUSE\n", " diffuse"},
654         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
655         {"#define USEVIEWTINT\n", " viewtint"},
656         {"#define USECOLORMAPPING\n", " colormapping"},
657         {"#define USESATURATION\n", " saturation"},
658         {"#define USEFOGINSIDE\n", " foginside"},
659         {"#define USEFOGOUTSIDE\n", " fogoutside"},
660         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
661         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
662         {"#define USEGAMMARAMPS\n", " gammaramps"},
663         {"#define USECUBEFILTER\n", " cubefilter"},
664         {"#define USEGLOW\n", " glow"},
665         {"#define USEBLOOM\n", " bloom"},
666         {"#define USESPECULAR\n", " specular"},
667         {"#define USEPOSTPROCESSING\n", " postprocessing"},
668         {"#define USEREFLECTION\n", " reflection"},
669         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
670         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
671         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
672         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
673         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
674         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
675         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
676         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
677         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
678         {"#define USEALPHAKILL\n", " alphakill"},
679         {"#define USEREFLECTCUBE\n", " reflectcube"},
680         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
681         {"#define USEBOUNCEGRID\n", " bouncegrid"},
682         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
683         {"#define USETRIPPY\n", " trippy"},
684 };
685
686 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
687 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 };
708
709 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
710 {
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
729 };
730
731 struct r_glsl_permutation_s;
732 typedef struct r_glsl_permutation_s
733 {
734         /// hash lookup data
735         struct r_glsl_permutation_s *hashnext;
736         unsigned int mode;
737         unsigned int permutation;
738
739         /// indicates if we have tried compiling this permutation already
740         qboolean compiled;
741         /// 0 if compilation failed
742         int program;
743         // texture units assigned to each detected uniform
744         int tex_Texture_First;
745         int tex_Texture_Second;
746         int tex_Texture_GammaRamps;
747         int tex_Texture_Normal;
748         int tex_Texture_Color;
749         int tex_Texture_Gloss;
750         int tex_Texture_Glow;
751         int tex_Texture_SecondaryNormal;
752         int tex_Texture_SecondaryColor;
753         int tex_Texture_SecondaryGloss;
754         int tex_Texture_SecondaryGlow;
755         int tex_Texture_Pants;
756         int tex_Texture_Shirt;
757         int tex_Texture_FogHeightTexture;
758         int tex_Texture_FogMask;
759         int tex_Texture_Lightmap;
760         int tex_Texture_Deluxemap;
761         int tex_Texture_Attenuation;
762         int tex_Texture_Cube;
763         int tex_Texture_Refraction;
764         int tex_Texture_Reflection;
765         int tex_Texture_ShadowMap2D;
766         int tex_Texture_CubeProjection;
767         int tex_Texture_ScreenDepth;
768         int tex_Texture_ScreenNormalMap;
769         int tex_Texture_ScreenDiffuse;
770         int tex_Texture_ScreenSpecular;
771         int tex_Texture_ReflectMask;
772         int tex_Texture_ReflectCube;
773         int tex_Texture_BounceGrid;
774         /// locations of detected uniforms in program object, or -1 if not found
775         int loc_Texture_First;
776         int loc_Texture_Second;
777         int loc_Texture_GammaRamps;
778         int loc_Texture_Normal;
779         int loc_Texture_Color;
780         int loc_Texture_Gloss;
781         int loc_Texture_Glow;
782         int loc_Texture_SecondaryNormal;
783         int loc_Texture_SecondaryColor;
784         int loc_Texture_SecondaryGloss;
785         int loc_Texture_SecondaryGlow;
786         int loc_Texture_Pants;
787         int loc_Texture_Shirt;
788         int loc_Texture_FogHeightTexture;
789         int loc_Texture_FogMask;
790         int loc_Texture_Lightmap;
791         int loc_Texture_Deluxemap;
792         int loc_Texture_Attenuation;
793         int loc_Texture_Cube;
794         int loc_Texture_Refraction;
795         int loc_Texture_Reflection;
796         int loc_Texture_ShadowMap2D;
797         int loc_Texture_CubeProjection;
798         int loc_Texture_ScreenDepth;
799         int loc_Texture_ScreenNormalMap;
800         int loc_Texture_ScreenDiffuse;
801         int loc_Texture_ScreenSpecular;
802         int loc_Texture_ReflectMask;
803         int loc_Texture_ReflectCube;
804         int loc_Texture_BounceGrid;
805         int loc_Alpha;
806         int loc_BloomBlur_Parameters;
807         int loc_ClientTime;
808         int loc_Color_Ambient;
809         int loc_Color_Diffuse;
810         int loc_Color_Specular;
811         int loc_Color_Glow;
812         int loc_Color_Pants;
813         int loc_Color_Shirt;
814         int loc_DeferredColor_Ambient;
815         int loc_DeferredColor_Diffuse;
816         int loc_DeferredColor_Specular;
817         int loc_DeferredMod_Diffuse;
818         int loc_DeferredMod_Specular;
819         int loc_DistortScaleRefractReflect;
820         int loc_EyePosition;
821         int loc_FogColor;
822         int loc_FogHeightFade;
823         int loc_FogPlane;
824         int loc_FogPlaneViewDist;
825         int loc_FogRangeRecip;
826         int loc_LightColor;
827         int loc_LightDir;
828         int loc_LightPosition;
829         int loc_OffsetMapping_ScaleSteps;
830         int loc_OffsetMapping_LodDistance;
831         int loc_PixelSize;
832         int loc_ReflectColor;
833         int loc_ReflectFactor;
834         int loc_ReflectOffset;
835         int loc_RefractColor;
836         int loc_Saturation;
837         int loc_ScreenCenterRefractReflect;
838         int loc_ScreenScaleRefractReflect;
839         int loc_ScreenToDepth;
840         int loc_ShadowMap_Parameters;
841         int loc_ShadowMap_TextureScale;
842         int loc_SpecularPower;
843         int loc_UserVec1;
844         int loc_UserVec2;
845         int loc_UserVec3;
846         int loc_UserVec4;
847         int loc_ViewTintColor;
848         int loc_ViewToLight;
849         int loc_ModelToLight;
850         int loc_TexMatrix;
851         int loc_BackgroundTexMatrix;
852         int loc_ModelViewProjectionMatrix;
853         int loc_ModelViewMatrix;
854         int loc_PixelToScreenTexCoord;
855         int loc_ModelToReflectCube;
856         int loc_ShadowMapMatrix;
857         int loc_BloomColorSubtract;
858         int loc_NormalmapScrollBlend;
859         int loc_BounceGridMatrix;
860         int loc_BounceGridIntensity;
861 }
862 r_glsl_permutation_t;
863
864 #define SHADERPERMUTATION_HASHSIZE 256
865
866
867 // non-degradable "lightweight" shader parameters to keep the permutations simpler
868 // these can NOT degrade! only use for simple stuff
869 enum
870 {
871         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
872         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
873         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
874         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
877         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
878         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
879 };
880 #define SHADERSTATICPARMS_COUNT 8
881
882 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
883 static int shaderstaticparms_count = 0;
884
885 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
886 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
887 qboolean R_CompileShader_CheckStaticParms(void)
888 {
889         static int r_compileshader_staticparms_save[1];
890         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
891         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
892
893         // detect all
894         if (r_glsl_saturation_redcompensate.integer)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
896         if (r_glsl_vertextextureblend_usebothalphas.integer)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
898         if (r_shadow_glossexact.integer)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
900         if (r_glsl_postprocess.integer)
901         {
902                 if (r_glsl_postprocess_uservec1_enable.integer)
903                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
904                 if (r_glsl_postprocess_uservec2_enable.integer)
905                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
906                 if (r_glsl_postprocess_uservec3_enable.integer)
907                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
908                 if (r_glsl_postprocess_uservec4_enable.integer)
909                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
910         }
911         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
912                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
913         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
914 }
915
916 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
917         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
918                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
919         else \
920                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
921 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
922 {
923         shaderstaticparms_count = 0;
924
925         // emit all
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
934 }
935
936 /// information about each possible shader permutation
937 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
938 /// currently selected permutation
939 r_glsl_permutation_t *r_glsl_permutation;
940 /// storage for permutations linked in the hash table
941 memexpandablearray_t r_glsl_permutationarray;
942
943 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
944 {
945         //unsigned int hashdepth = 0;
946         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
947         r_glsl_permutation_t *p;
948         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
949         {
950                 if (p->mode == mode && p->permutation == permutation)
951                 {
952                         //if (hashdepth > 10)
953                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
954                         return p;
955                 }
956                 //hashdepth++;
957         }
958         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
959         p->mode = mode;
960         p->permutation = permutation;
961         p->hashnext = r_glsl_permutationhash[mode][hashindex];
962         r_glsl_permutationhash[mode][hashindex] = p;
963         //if (hashdepth > 10)
964         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
965         return p;
966 }
967
968 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
969 {
970         char *shaderstring;
971         if (!filename || !filename[0])
972                 return NULL;
973         if (!strcmp(filename, "glsl/default.glsl"))
974         {
975                 if (!glslshaderstring)
976                 {
977                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
978                         if (glslshaderstring)
979                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
980                         else
981                                 glslshaderstring = (char *)builtinshaderstring;
982                 }
983                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
984                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
985                 return shaderstring;
986         }
987         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
988         if (shaderstring)
989         {
990                 if (printfromdisknotice)
991                         Con_DPrintf("from disk %s... ", filename);
992                 return shaderstring;
993         }
994         return shaderstring;
995 }
996
997 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
998 {
999         int i;
1000         int sampler;
1001         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1002         char *vertexstring, *geometrystring, *fragmentstring;
1003         char permutationname[256];
1004         int vertstrings_count = 0;
1005         int geomstrings_count = 0;
1006         int fragstrings_count = 0;
1007         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1008         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1009         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1010
1011         if (p->compiled)
1012                 return;
1013         p->compiled = true;
1014         p->program = 0;
1015
1016         permutationname[0] = 0;
1017         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1018         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1019         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1020
1021         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1022
1023         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1024         if(vid.support.gl20shaders130)
1025         {
1026                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1027                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1028                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1029                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1030                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1031                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1032         }
1033
1034         // the first pretext is which type of shader to compile as
1035         // (later these will all be bound together as a program object)
1036         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1037         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1038         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1039
1040         // the second pretext is the mode (for example a light source)
1041         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1042         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1043         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1044         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1045
1046         // now add all the permutation pretexts
1047         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1048         {
1049                 if (permutation & (1<<i))
1050                 {
1051                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1052                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1055                 }
1056                 else
1057                 {
1058                         // keep line numbers correct
1059                         vertstrings_list[vertstrings_count++] = "\n";
1060                         geomstrings_list[geomstrings_count++] = "\n";
1061                         fragstrings_list[fragstrings_count++] = "\n";
1062                 }
1063         }
1064
1065         // add static parms
1066         R_CompileShader_AddStaticParms(mode, permutation);
1067         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1068         vertstrings_count += shaderstaticparms_count;
1069         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         geomstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         fragstrings_count += shaderstaticparms_count;
1073
1074         // now append the shader text itself
1075         vertstrings_list[vertstrings_count++] = vertexstring;
1076         geomstrings_list[geomstrings_count++] = geometrystring;
1077         fragstrings_list[fragstrings_count++] = fragmentstring;
1078
1079         // if any sources were NULL, clear the respective list
1080         if (!vertexstring)
1081                 vertstrings_count = 0;
1082         if (!geometrystring)
1083                 geomstrings_count = 0;
1084         if (!fragmentstring)
1085                 fragstrings_count = 0;
1086
1087         // compile the shader program
1088         if (vertstrings_count + geomstrings_count + fragstrings_count)
1089                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1090         if (p->program)
1091         {
1092                 CHECKGLERROR
1093                 qglUseProgram(p->program);CHECKGLERROR
1094                 // look up all the uniform variable names we care about, so we don't
1095                 // have to look them up every time we set them
1096
1097                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1098                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1099                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1100                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1101                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1102                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1103                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1104                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1105                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1106                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1107                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1108                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1109                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1110                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1111                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1112                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1113                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1114                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1115                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1116                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1117                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1118                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1119                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1120                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1154                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1155                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1156                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1157                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1158                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1159                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1160                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1161                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1162                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1163                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1164                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1165                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1166                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1167                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1168                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1169                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1170                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1171                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1172                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1173                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1174                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1175                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1176                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1177                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1178                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1179                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1180                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1181                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1182                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1183                 // initialize the samplers to refer to the texture units we use
1184                 p->tex_Texture_First = -1;
1185                 p->tex_Texture_Second = -1;
1186                 p->tex_Texture_GammaRamps = -1;
1187                 p->tex_Texture_Normal = -1;
1188                 p->tex_Texture_Color = -1;
1189                 p->tex_Texture_Gloss = -1;
1190                 p->tex_Texture_Glow = -1;
1191                 p->tex_Texture_SecondaryNormal = -1;
1192                 p->tex_Texture_SecondaryColor = -1;
1193                 p->tex_Texture_SecondaryGloss = -1;
1194                 p->tex_Texture_SecondaryGlow = -1;
1195                 p->tex_Texture_Pants = -1;
1196                 p->tex_Texture_Shirt = -1;
1197                 p->tex_Texture_FogHeightTexture = -1;
1198                 p->tex_Texture_FogMask = -1;
1199                 p->tex_Texture_Lightmap = -1;
1200                 p->tex_Texture_Deluxemap = -1;
1201                 p->tex_Texture_Attenuation = -1;
1202                 p->tex_Texture_Cube = -1;
1203                 p->tex_Texture_Refraction = -1;
1204                 p->tex_Texture_Reflection = -1;
1205                 p->tex_Texture_ShadowMap2D = -1;
1206                 p->tex_Texture_CubeProjection = -1;
1207                 p->tex_Texture_ScreenDepth = -1;
1208                 p->tex_Texture_ScreenNormalMap = -1;
1209                 p->tex_Texture_ScreenDiffuse = -1;
1210                 p->tex_Texture_ScreenSpecular = -1;
1211                 p->tex_Texture_ReflectMask = -1;
1212                 p->tex_Texture_ReflectCube = -1;
1213                 p->tex_Texture_BounceGrid = -1;
1214                 sampler = 0;
1215                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1216                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1217                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1218                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1219                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1220                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1221                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1226                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1227                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1228                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1230                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1231                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1232                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1233                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1234                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1235                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1236                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1237                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1244                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1245                 CHECKGLERROR
1246                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1247         }
1248         else
1249                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1250
1251         // free the strings
1252         if (vertexstring)
1253                 Mem_Free(vertexstring);
1254         if (geometrystring)
1255                 Mem_Free(geometrystring);
1256         if (fragmentstring)
1257                 Mem_Free(fragmentstring);
1258 }
1259
1260 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1261 {
1262         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263         if (r_glsl_permutation != perm)
1264         {
1265                 r_glsl_permutation = perm;
1266                 if (!r_glsl_permutation->program)
1267                 {
1268                         if (!r_glsl_permutation->compiled)
1269                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                         if (!r_glsl_permutation->program)
1271                         {
1272                                 // remove features until we find a valid permutation
1273                                 int i;
1274                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275                                 {
1276                                         // reduce i more quickly whenever it would not remove any bits
1277                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278                                         if (!(permutation & j))
1279                                                 continue;
1280                                         permutation -= j;
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         if (!r_glsl_permutation->compiled)
1283                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1284                                         if (r_glsl_permutation->program)
1285                                                 break;
1286                                 }
1287                                 if (i >= SHADERPERMUTATION_COUNT)
1288                                 {
1289                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         qglUseProgram(0);CHECKGLERROR
1292                                         return; // no bit left to clear, entire mode is broken
1293                                 }
1294                         }
1295                 }
1296                 CHECKGLERROR
1297                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1298         }
1299         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1302 }
1303
1304 #ifdef SUPPORTD3D
1305
1306 #ifdef SUPPORTD3D
1307 #include <d3d9.h>
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1310 #endif
1311
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1314 {
1315         /// hash lookup data
1316         struct r_hlsl_permutation_s *hashnext;
1317         unsigned int mode;
1318         unsigned int permutation;
1319
1320         /// indicates if we have tried compiling this permutation already
1321         qboolean compiled;
1322         /// NULL if compilation failed
1323         IDirect3DVertexShader9 *vertexshader;
1324         IDirect3DPixelShader9 *pixelshader;
1325 }
1326 r_hlsl_permutation_t;
1327
1328 typedef enum D3DVSREGISTER_e
1329 {
1330         D3DVSREGISTER_TexMatrix = 0, // float4x4
1331         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335         D3DVSREGISTER_ModelToLight = 20, // float4x4
1336         D3DVSREGISTER_EyePosition = 24,
1337         D3DVSREGISTER_FogPlane = 25,
1338         D3DVSREGISTER_LightDir = 26,
1339         D3DVSREGISTER_LightPosition = 27,
1340 }
1341 D3DVSREGISTER_t;
1342
1343 typedef enum D3DPSREGISTER_e
1344 {
1345         D3DPSREGISTER_Alpha = 0,
1346         D3DPSREGISTER_BloomBlur_Parameters = 1,
1347         D3DPSREGISTER_ClientTime = 2,
1348         D3DPSREGISTER_Color_Ambient = 3,
1349         D3DPSREGISTER_Color_Diffuse = 4,
1350         D3DPSREGISTER_Color_Specular = 5,
1351         D3DPSREGISTER_Color_Glow = 6,
1352         D3DPSREGISTER_Color_Pants = 7,
1353         D3DPSREGISTER_Color_Shirt = 8,
1354         D3DPSREGISTER_DeferredColor_Ambient = 9,
1355         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356         D3DPSREGISTER_DeferredColor_Specular = 11,
1357         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358         D3DPSREGISTER_DeferredMod_Specular = 13,
1359         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360         D3DPSREGISTER_EyePosition = 15, // unused
1361         D3DPSREGISTER_FogColor = 16,
1362         D3DPSREGISTER_FogHeightFade = 17,
1363         D3DPSREGISTER_FogPlane = 18,
1364         D3DPSREGISTER_FogPlaneViewDist = 19,
1365         D3DPSREGISTER_FogRangeRecip = 20,
1366         D3DPSREGISTER_LightColor = 21,
1367         D3DPSREGISTER_LightDir = 22, // unused
1368         D3DPSREGISTER_LightPosition = 23,
1369         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370         D3DPSREGISTER_PixelSize = 25,
1371         D3DPSREGISTER_ReflectColor = 26,
1372         D3DPSREGISTER_ReflectFactor = 27,
1373         D3DPSREGISTER_ReflectOffset = 28,
1374         D3DPSREGISTER_RefractColor = 29,
1375         D3DPSREGISTER_Saturation = 30,
1376         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378         D3DPSREGISTER_ScreenToDepth = 33,
1379         D3DPSREGISTER_ShadowMap_Parameters = 34,
1380         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381         D3DPSREGISTER_SpecularPower = 36,
1382         D3DPSREGISTER_UserVec1 = 37,
1383         D3DPSREGISTER_UserVec2 = 38,
1384         D3DPSREGISTER_UserVec3 = 39,
1385         D3DPSREGISTER_UserVec4 = 40,
1386         D3DPSREGISTER_ViewTintColor = 41,
1387         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388         D3DPSREGISTER_BloomColorSubtract = 43,
1389         D3DPSREGISTER_ViewToLight = 44, // float4x4
1390         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391         D3DPSREGISTER_NormalmapScrollBlend = 52,
1392         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1393         // next at 54
1394 }
1395 D3DPSREGISTER_t;
1396
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1403
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 {
1406         //unsigned int hashdepth = 0;
1407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408         r_hlsl_permutation_t *p;
1409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410         {
1411                 if (p->mode == mode && p->permutation == permutation)
1412                 {
1413                         //if (hashdepth > 10)
1414                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415                         return p;
1416                 }
1417                 //hashdepth++;
1418         }
1419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420         p->mode = mode;
1421         p->permutation = permutation;
1422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423         r_hlsl_permutationhash[mode][hashindex] = p;
1424         //if (hashdepth > 10)
1425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1426         return p;
1427 }
1428
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1430 {
1431         char *shaderstring;
1432         if (!filename || !filename[0])
1433                 return NULL;
1434         if (!strcmp(filename, "hlsl/default.hlsl"))
1435         {
1436                 if (!hlslshaderstring)
1437                 {
1438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439                         if (hlslshaderstring)
1440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441                         else
1442                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1443                 }
1444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446                 return shaderstring;
1447         }
1448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449         if (shaderstring)
1450         {
1451                 if (printfromdisknotice)
1452                         Con_DPrintf("from disk %s... ", filename);
1453                 return shaderstring;
1454         }
1455         return shaderstring;
1456 }
1457
1458 #include <d3dx9.h>
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1461
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 {
1464         DWORD *vsbin = NULL;
1465         DWORD *psbin = NULL;
1466         fs_offset_t vsbinsize;
1467         fs_offset_t psbinsize;
1468 //      IDirect3DVertexShader9 *vs = NULL;
1469 //      IDirect3DPixelShader9 *ps = NULL;
1470         ID3DXBuffer *vslog = NULL;
1471         ID3DXBuffer *vsbuffer = NULL;
1472         ID3DXConstantTable *vsconstanttable = NULL;
1473         ID3DXBuffer *pslog = NULL;
1474         ID3DXBuffer *psbuffer = NULL;
1475         ID3DXConstantTable *psconstanttable = NULL;
1476         int vsresult = 0;
1477         int psresult = 0;
1478         char temp[MAX_INPUTLINE];
1479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480         qboolean debugshader = gl_paranoid.integer != 0;
1481         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1483         if (!debugshader)
1484         {
1485                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1486                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1487         }
1488         if ((!vsbin && vertstring) || (!psbin && fragstring))
1489         {
1490                 const char* dllnames_d3dx9 [] =
1491                 {
1492                         "d3dx9_43.dll",
1493                         "d3dx9_42.dll",
1494                         "d3dx9_41.dll",
1495                         "d3dx9_40.dll",
1496                         "d3dx9_39.dll",
1497                         "d3dx9_38.dll",
1498                         "d3dx9_37.dll",
1499                         "d3dx9_36.dll",
1500                         "d3dx9_35.dll",
1501                         "d3dx9_34.dll",
1502                         "d3dx9_33.dll",
1503                         "d3dx9_32.dll",
1504                         "d3dx9_31.dll",
1505                         "d3dx9_30.dll",
1506                         "d3dx9_29.dll",
1507                         "d3dx9_28.dll",
1508                         "d3dx9_27.dll",
1509                         "d3dx9_26.dll",
1510                         "d3dx9_25.dll",
1511                         "d3dx9_24.dll",
1512                         NULL
1513                 };
1514                 dllhandle_t d3dx9_dll = NULL;
1515                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1516                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1517                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518                 dllfunction_t d3dx9_dllfuncs[] =
1519                 {
1520                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1521                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1522                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1523                         {NULL, NULL}
1524                 };
1525                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1526                 {
1527                         DWORD shaderflags = 0;
1528                         if (debugshader)
1529                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1530                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1531                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1532                         if (vertstring && vertstring[0])
1533                         {
1534                                 if (debugshader)
1535                                 {
1536 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1537 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1538                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1539                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1540                                 }
1541                                 else
1542                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1543                                 if (vsbuffer)
1544                                 {
1545                                         vsbinsize = vsbuffer->GetBufferSize();
1546                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1547                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1548                                         vsbuffer->Release();
1549                                 }
1550                                 if (vslog)
1551                                 {
1552                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1553                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1554                                         vslog->Release();
1555                                 }
1556                         }
1557                         if (fragstring && fragstring[0])
1558                         {
1559                                 if (debugshader)
1560                                 {
1561 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1562 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1563                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1564                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1565                                 }
1566                                 else
1567                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1568                                 if (psbuffer)
1569                                 {
1570                                         psbinsize = psbuffer->GetBufferSize();
1571                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1572                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1573                                         psbuffer->Release();
1574                                 }
1575                                 if (pslog)
1576                                 {
1577                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1578                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1579                                         pslog->Release();
1580                                 }
1581                         }
1582                         Sys_UnloadLibrary(&d3dx9_dll);
1583                 }
1584                 else
1585                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1586         }
1587         if (vsbin && psbin)
1588         {
1589                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1590                 if (FAILED(vsresult))
1591                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1592                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1593                 if (FAILED(psresult))
1594                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1595         }
1596         // free the shader data
1597         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1598         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1599 }
1600
1601 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1602 {
1603         int i;
1604         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1605         int vertstring_length = 0;
1606         int geomstring_length = 0;
1607         int fragstring_length = 0;
1608         char *t;
1609         char *vertexstring, *geometrystring, *fragmentstring;
1610         char *vertstring, *geomstring, *fragstring;
1611         char permutationname[256];
1612         char cachename[256];
1613         int vertstrings_count = 0;
1614         int geomstrings_count = 0;
1615         int fragstrings_count = 0;
1616         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1617         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1618         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1619
1620         if (p->compiled)
1621                 return;
1622         p->compiled = true;
1623         p->vertexshader = NULL;
1624         p->pixelshader = NULL;
1625
1626         permutationname[0] = 0;
1627         cachename[0] = 0;
1628         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1629         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1630         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1631
1632         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1633         strlcat(cachename, "hlsl/", sizeof(cachename));
1634
1635         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1636         vertstrings_count = 0;
1637         geomstrings_count = 0;
1638         fragstrings_count = 0;
1639         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1640         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1641         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1642
1643         // the first pretext is which type of shader to compile as
1644         // (later these will all be bound together as a program object)
1645         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1646         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1647         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1648
1649         // the second pretext is the mode (for example a light source)
1650         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1651         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1652         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1653         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1654         strlcat(cachename, modeinfo->name, sizeof(cachename));
1655
1656         // now add all the permutation pretexts
1657         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1658         {
1659                 if (permutation & (1<<i))
1660                 {
1661                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1662                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1665                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1666                 }
1667                 else
1668                 {
1669                         // keep line numbers correct
1670                         vertstrings_list[vertstrings_count++] = "\n";
1671                         geomstrings_list[geomstrings_count++] = "\n";
1672                         fragstrings_list[fragstrings_count++] = "\n";
1673                 }
1674         }
1675
1676         // add static parms
1677         R_CompileShader_AddStaticParms(mode, permutation);
1678         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1679         vertstrings_count += shaderstaticparms_count;
1680         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         geomstrings_count += shaderstaticparms_count;
1682         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         fragstrings_count += shaderstaticparms_count;
1684
1685         // replace spaces in the cachename with _ characters
1686         for (i = 0;cachename[i];i++)
1687                 if (cachename[i] == ' ')
1688                         cachename[i] = '_';
1689
1690         // now append the shader text itself
1691         vertstrings_list[vertstrings_count++] = vertexstring;
1692         geomstrings_list[geomstrings_count++] = geometrystring;
1693         fragstrings_list[fragstrings_count++] = fragmentstring;
1694
1695         // if any sources were NULL, clear the respective list
1696         if (!vertexstring)
1697                 vertstrings_count = 0;
1698         if (!geometrystring)
1699                 geomstrings_count = 0;
1700         if (!fragmentstring)
1701                 fragstrings_count = 0;
1702
1703         vertstring_length = 0;
1704         for (i = 0;i < vertstrings_count;i++)
1705                 vertstring_length += strlen(vertstrings_list[i]);
1706         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1707         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1708                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1709
1710         geomstring_length = 0;
1711         for (i = 0;i < geomstrings_count;i++)
1712                 geomstring_length += strlen(geomstrings_list[i]);
1713         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1714         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1715                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1716
1717         fragstring_length = 0;
1718         for (i = 0;i < fragstrings_count;i++)
1719                 fragstring_length += strlen(fragstrings_list[i]);
1720         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1721         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1722                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1723
1724         // try to load the cached shader, or generate one
1725         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1726
1727         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1728                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1729         else
1730                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1731
1732         // free the strings
1733         if (vertstring)
1734                 Mem_Free(vertstring);
1735         if (geomstring)
1736                 Mem_Free(geomstring);
1737         if (fragstring)
1738                 Mem_Free(fragstring);
1739         if (vertexstring)
1740                 Mem_Free(vertexstring);
1741         if (geometrystring)
1742                 Mem_Free(geometrystring);
1743         if (fragmentstring)
1744                 Mem_Free(fragmentstring);
1745 }
1746
1747 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1748 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1749 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1750 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1751 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1752 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1753
1754 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1755 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1756 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1757 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1758 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1759 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1760
1761 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1762 {
1763         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1764         if (r_hlsl_permutation != perm)
1765         {
1766                 r_hlsl_permutation = perm;
1767                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1768                 {
1769                         if (!r_hlsl_permutation->compiled)
1770                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1771                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1772                         {
1773                                 // remove features until we find a valid permutation
1774                                 int i;
1775                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1776                                 {
1777                                         // reduce i more quickly whenever it would not remove any bits
1778                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1779                                         if (!(permutation & j))
1780                                                 continue;
1781                                         permutation -= j;
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         if (!r_hlsl_permutation->compiled)
1784                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1785                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1786                                                 break;
1787                                 }
1788                                 if (i >= SHADERPERMUTATION_COUNT)
1789                                 {
1790                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1791                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1792                                         return; // no bit left to clear, entire mode is broken
1793                                 }
1794                         }
1795                 }
1796                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1797                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1798         }
1799         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1800         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1801         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1802 }
1803 #endif
1804
1805 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1806 {
1807         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1808         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1809         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1810         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1811 }
1812
1813 void R_GLSL_Restart_f(void)
1814 {
1815         unsigned int i, limit;
1816         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1817                 Mem_Free(glslshaderstring);
1818         glslshaderstring = NULL;
1819         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1820                 Mem_Free(hlslshaderstring);
1821         hlslshaderstring = NULL;
1822         switch(vid.renderpath)
1823         {
1824         case RENDERPATH_D3D9:
1825 #ifdef SUPPORTD3D
1826                 {
1827                         r_hlsl_permutation_t *p;
1828                         r_hlsl_permutation = NULL;
1829                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1830                         for (i = 0;i < limit;i++)
1831                         {
1832                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1833                                 {
1834                                         if (p->vertexshader)
1835                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1836                                         if (p->pixelshader)
1837                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1838                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1842                 }
1843 #endif
1844                 break;
1845         case RENDERPATH_D3D10:
1846                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1847                 break;
1848         case RENDERPATH_D3D11:
1849                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1850                 break;
1851         case RENDERPATH_GL20:
1852         case RENDERPATH_GLES2:
1853                 {
1854                         r_glsl_permutation_t *p;
1855                         r_glsl_permutation = NULL;
1856                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1857                         for (i = 0;i < limit;i++)
1858                         {
1859                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1860                                 {
1861                                         GL_Backend_FreeProgram(p->program);
1862                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1863                                 }
1864                         }
1865                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1866                 }
1867                 break;
1868         case RENDERPATH_GL11:
1869         case RENDERPATH_GL13:
1870         case RENDERPATH_GLES1:
1871                 break;
1872         case RENDERPATH_SOFT:
1873                 break;
1874         }
1875 }
1876
1877 void R_GLSL_DumpShader_f(void)
1878 {
1879         int i;
1880         qfile_t *file;
1881
1882         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1883         if (file)
1884         {
1885                 FS_Print(file, "/* The engine may define the following macros:\n");
1886                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1887                 for (i = 0;i < SHADERMODE_COUNT;i++)
1888                         FS_Print(file, glslshadermodeinfo[i].pretext);
1889                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1890                         FS_Print(file, shaderpermutationinfo[i].pretext);
1891                 FS_Print(file, "*/\n");
1892                 FS_Print(file, builtinshaderstring);
1893                 FS_Close(file);
1894                 Con_Printf("glsl/default.glsl written\n");
1895         }
1896         else
1897                 Con_Printf("failed to write to glsl/default.glsl\n");
1898
1899         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1900         if (file)
1901         {
1902                 FS_Print(file, "/* The engine may define the following macros:\n");
1903                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1904                 for (i = 0;i < SHADERMODE_COUNT;i++)
1905                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1906                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1907                         FS_Print(file, shaderpermutationinfo[i].pretext);
1908                 FS_Print(file, "*/\n");
1909                 FS_Print(file, builtinhlslshaderstring);
1910                 FS_Close(file);
1911                 Con_Printf("hlsl/default.hlsl written\n");
1912         }
1913         else
1914                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1915 }
1916
1917 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1918 {
1919         unsigned int permutation = 0;
1920         if (r_trippy.integer && !notrippy)
1921                 permutation |= SHADERPERMUTATION_TRIPPY;
1922         permutation |= SHADERPERMUTATION_VIEWTINT;
1923         if (first)
1924                 permutation |= SHADERPERMUTATION_DIFFUSE;
1925         if (second)
1926                 permutation |= SHADERPERMUTATION_SPECULAR;
1927         if (texturemode == GL_MODULATE)
1928                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1929         else if (texturemode == GL_ADD)
1930                 permutation |= SHADERPERMUTATION_GLOW;
1931         else if (texturemode == GL_DECAL)
1932                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1933         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1934                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1935         if (!second)
1936                 texturemode = GL_MODULATE;
1937         if (vid.allowalphatocoverage)
1938                 GL_AlphaToCoverage(false);
1939         switch (vid.renderpath)
1940         {
1941         case RENDERPATH_D3D9:
1942 #ifdef SUPPORTD3D
1943                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1944                 R_Mesh_TexBind(GL20TU_FIRST , first );
1945                 R_Mesh_TexBind(GL20TU_SECOND, second);
1946                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1947                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1948 #endif
1949                 break;
1950         case RENDERPATH_D3D10:
1951                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1952                 break;
1953         case RENDERPATH_D3D11:
1954                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_GL20:
1957         case RENDERPATH_GLES2:
1958                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1959                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1960                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1961                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1962                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1963                 break;
1964         case RENDERPATH_GL13:
1965         case RENDERPATH_GLES1:
1966                 R_Mesh_TexBind(0, first );
1967                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1968                 R_Mesh_TexBind(1, second);
1969                 if (second)
1970                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1971                 break;
1972         case RENDERPATH_GL11:
1973                 R_Mesh_TexBind(0, first );
1974                 break;
1975         case RENDERPATH_SOFT:
1976                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1977                 R_Mesh_TexBind(GL20TU_FIRST , first );
1978                 R_Mesh_TexBind(GL20TU_SECOND, second);
1979                 break;
1980         }
1981 }
1982
1983 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1984 {
1985         unsigned int permutation = 0;
1986         if (r_trippy.integer && !notrippy)
1987                 permutation |= SHADERPERMUTATION_TRIPPY;
1988         if (vid.allowalphatocoverage)
1989                 GL_AlphaToCoverage(false);
1990         switch (vid.renderpath)
1991         {
1992         case RENDERPATH_D3D9:
1993 #ifdef SUPPORTD3D
1994                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         case RENDERPATH_GL13:
2008         case RENDERPATH_GLES1:
2009                 R_Mesh_TexBind(0, 0);
2010                 R_Mesh_TexBind(1, 0);
2011                 break;
2012         case RENDERPATH_GL11:
2013                 R_Mesh_TexBind(0, 0);
2014                 break;
2015         case RENDERPATH_SOFT:
2016                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         }
2019 }
2020
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 {
2023         int permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         if (vid.allowalphatocoverage)
2027                 GL_AlphaToCoverage(false);
2028         switch (vid.renderpath)
2029         {
2030         case RENDERPATH_D3D9:
2031 #ifdef SUPPORTHLSL
2032                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2033 #endif
2034                 break;
2035         case RENDERPATH_D3D10:
2036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037                 break;
2038         case RENDERPATH_D3D11:
2039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_GL20:
2042         case RENDERPATH_GLES2:
2043                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 break;
2048         case RENDERPATH_GL11:
2049                 break;
2050         case RENDERPATH_SOFT:
2051                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         }
2054 }
2055
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern cvar_t r_shadow_deferred_8bitrange;
2058 extern rtexture_t *r_shadow_attenuationgradienttexture;
2059 extern rtexture_t *r_shadow_attenuation2dtexture;
2060 extern rtexture_t *r_shadow_attenuation3dtexture;
2061 extern qboolean r_shadow_usingshadowmap2d;
2062 extern qboolean r_shadow_usingshadowmaportho;
2063 extern float r_shadow_shadowmap_texturescale[2];
2064 extern float r_shadow_shadowmap_parameters[4];
2065 extern qboolean r_shadow_shadowmapvsdct;
2066 extern qboolean r_shadow_shadowmapsampler;
2067 extern int r_shadow_shadowmappcf;
2068 extern rtexture_t *r_shadow_shadowmap2dtexture;
2069 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2070 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2071 extern matrix4x4_t r_shadow_shadowmapmatrix;
2072 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2073 extern int r_shadow_prepass_width;
2074 extern int r_shadow_prepass_height;
2075 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2076 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2077 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2078 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2079 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2080
2081 #define BLENDFUNC_ALLOWS_COLORMOD      1
2082 #define BLENDFUNC_ALLOWS_FOG           2
2083 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2084 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2085 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2086 static int R_BlendFuncFlags(int src, int dst)
2087 {
2088         int r = 0;
2089
2090         // a blendfunc allows colormod if:
2091         // a) it can never keep the destination pixel invariant, or
2092         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2093         // this is to prevent unintended side effects from colormod
2094
2095         // a blendfunc allows fog if:
2096         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2097         // this is to prevent unintended side effects from fog
2098
2099         // these checks are the output of fogeval.pl
2100
2101         r |= BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2111         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2115         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123
2124         return r;
2125 }
2126
2127 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2128 {
2129         // select a permutation of the lighting shader appropriate to this
2130         // combination of texture, entity, light source, and fogging, only use the
2131         // minimum features necessary to avoid wasting rendering time in the
2132         // fragment shader on features that are not being used
2133         unsigned int permutation = 0;
2134         unsigned int mode = 0;
2135         int blendfuncflags;
2136         static float dummy_colormod[3] = {1, 1, 1};
2137         float *colormod = rsurface.colormod;
2138         float m16f[16];
2139         matrix4x4_t tempmatrix;
2140         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2141         if (r_trippy.integer && !notrippy)
2142                 permutation |= SHADERPERMUTATION_TRIPPY;
2143         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2144                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2145         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2146                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2147         if (rsurfacepass == RSURFPASS_BACKGROUND)
2148         {
2149                 // distorted background
2150                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2151                 {
2152                         mode = SHADERMODE_WATER;
2153                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2154                         {
2155                                 // this is the right thing to do for wateralpha
2156                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2157                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2158                         }
2159                         else
2160                         {
2161                                 // this is the right thing to do for entity alpha
2162                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2163                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2164                         }
2165                 }
2166                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2167                 {
2168                         mode = SHADERMODE_REFRACTION;
2169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                 }
2172                 else
2173                 {
2174                         mode = SHADERMODE_GENERIC;
2175                         permutation |= SHADERPERMUTATION_DIFFUSE;
2176                         GL_BlendFunc(GL_ONE, GL_ZERO);
2177                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178                 }
2179                 if (vid.allowalphatocoverage)
2180                         GL_AlphaToCoverage(false);
2181         }
2182         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2183         {
2184                 if (r_glsl_offsetmapping.integer)
2185                 {
2186                         switch(rsurface.texture->offsetmapping)
2187                         {
2188                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191                         case OFFSETMAPPING_OFF: break;
2192                         }
2193                 }
2194                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196                 // normalmap (deferred prepass), may use alpha test on diffuse
2197                 mode = SHADERMODE_DEFERREDGEOMETRY;
2198                 GL_BlendFunc(GL_ONE, GL_ZERO);
2199                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200                 if (vid.allowalphatocoverage)
2201                         GL_AlphaToCoverage(false);
2202         }
2203         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2204         {
2205                 if (r_glsl_offsetmapping.integer)
2206                 {
2207                         switch(rsurface.texture->offsetmapping)
2208                         {
2209                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212                         case OFFSETMAPPING_OFF: break;
2213                         }
2214                 }
2215                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2217                 // light source
2218                 mode = SHADERMODE_LIGHTSOURCE;
2219                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2220                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2221                 if (diffusescale > 0)
2222                         permutation |= SHADERPERMUTATION_DIFFUSE;
2223                 if (specularscale > 0)
2224                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2225                 if (r_refdef.fogenabled)
2226                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2227                 if (rsurface.texture->colormapping)
2228                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2229                 if (r_shadow_usingshadowmap2d)
2230                 {
2231                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2232                         if(r_shadow_shadowmapvsdct)
2233                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2234
2235                         if (r_shadow_shadowmapsampler)
2236                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2237                         if (r_shadow_shadowmappcf > 1)
2238                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2239                         else if (r_shadow_shadowmappcf)
2240                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2241                 }
2242                 if (rsurface.texture->reflectmasktexture)
2243                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2244                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2245                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2246                 if (vid.allowalphatocoverage)
2247                         GL_AlphaToCoverage(false);
2248         }
2249         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2250         {
2251                 if (r_glsl_offsetmapping.integer)
2252                 {
2253                         switch(rsurface.texture->offsetmapping)
2254                         {
2255                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258                         case OFFSETMAPPING_OFF: break;
2259                         }
2260                 }
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263                 // unshaded geometry (fullbright or ambient model lighting)
2264                 mode = SHADERMODE_FLATCOLOR;
2265                 ambientscale = diffusescale = specularscale = 0;
2266                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267                         permutation |= SHADERPERMUTATION_GLOW;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmapsampler)
2278                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2279                         if (r_shadow_shadowmappcf > 1)
2280                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2281                         else if (r_shadow_shadowmappcf)
2282                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2283                 }
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2285                         permutation |= SHADERPERMUTATION_REFLECTION;
2286                 if (rsurface.texture->reflectmasktexture)
2287                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2288                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2289                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2290                 // when using alphatocoverage, we don't need alphakill
2291                 if (vid.allowalphatocoverage)
2292                 {
2293                         if (r_transparent_alphatocoverage.integer)
2294                         {
2295                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2296                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2297                         }
2298                         else
2299                                 GL_AlphaToCoverage(false);
2300                 }
2301         }
2302         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2303         {
2304                 if (r_glsl_offsetmapping.integer)
2305                 {
2306                         switch(rsurface.texture->offsetmapping)
2307                         {
2308                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2309                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2310                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2311                         case OFFSETMAPPING_OFF: break;
2312                         }
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2315                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2316                 // directional model lighting
2317                 mode = SHADERMODE_LIGHTDIRECTION;
2318                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2319                         permutation |= SHADERPERMUTATION_GLOW;
2320                 permutation |= SHADERPERMUTATION_DIFFUSE;
2321                 if (specularscale > 0)
2322                         permutation |= SHADERPERMUTATION_SPECULAR;
2323                 if (r_refdef.fogenabled)
2324                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2325                 if (rsurface.texture->colormapping)
2326                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2327                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2328                 {
2329                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2330                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2331
2332                         if (r_shadow_shadowmapsampler)
2333                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2334                         if (r_shadow_shadowmappcf > 1)
2335                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2336                         else if (r_shadow_shadowmappcf)
2337                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2338                 }
2339                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2340                         permutation |= SHADERPERMUTATION_REFLECTION;
2341                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2342                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2343                 if (rsurface.texture->reflectmasktexture)
2344                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2345                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2346                 {
2347                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2348                         if (r_shadow_bouncegriddirectional)
2349                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2350                 }
2351                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353                 // when using alphatocoverage, we don't need alphakill
2354                 if (vid.allowalphatocoverage)
2355                 {
2356                         if (r_transparent_alphatocoverage.integer)
2357                         {
2358                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2360                         }
2361                         else
2362                                 GL_AlphaToCoverage(false);
2363                 }
2364         }
2365         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2366         {
2367                 if (r_glsl_offsetmapping.integer)
2368                 {
2369                         switch(rsurface.texture->offsetmapping)
2370                         {
2371                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374                         case OFFSETMAPPING_OFF: break;
2375                         }
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379                 // ambient model lighting
2380                 mode = SHADERMODE_LIGHTDIRECTION;
2381                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2382                         permutation |= SHADERPERMUTATION_GLOW;
2383                 if (r_refdef.fogenabled)
2384                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2385                 if (rsurface.texture->colormapping)
2386                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2387                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2388                 {
2389                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2390                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2391
2392                         if (r_shadow_shadowmapsampler)
2393                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2394                         if (r_shadow_shadowmappcf > 1)
2395                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2396                         else if (r_shadow_shadowmappcf)
2397                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2398                 }
2399                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2400                         permutation |= SHADERPERMUTATION_REFLECTION;
2401                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2402                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2403                 if (rsurface.texture->reflectmasktexture)
2404                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2405                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2406                 {
2407                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2408                         if (r_shadow_bouncegriddirectional)
2409                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2410                 }
2411                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2412                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 // when using alphatocoverage, we don't need alphakill
2414                 if (vid.allowalphatocoverage)
2415                 {
2416                         if (r_transparent_alphatocoverage.integer)
2417                         {
2418                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2419                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2420                         }
2421                         else
2422                                 GL_AlphaToCoverage(false);
2423                 }
2424         }
2425         else
2426         {
2427                 if (r_glsl_offsetmapping.integer)
2428                 {
2429                         switch(rsurface.texture->offsetmapping)
2430                         {
2431                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2432                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2433                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434                         case OFFSETMAPPING_OFF: break;
2435                         }
2436                 }
2437                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2438                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2439                 // lightmapped wall
2440                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2441                         permutation |= SHADERPERMUTATION_GLOW;
2442                 if (r_refdef.fogenabled)
2443                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2444                 if (rsurface.texture->colormapping)
2445                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2446                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2447                 {
2448                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2449                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2450
2451                         if (r_shadow_shadowmapsampler)
2452                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2453                         if (r_shadow_shadowmappcf > 1)
2454                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2455                         else if (r_shadow_shadowmappcf)
2456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (FAKELIGHT_ENABLED)
2465                 {
2466                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467                         mode = SHADERMODE_FAKELIGHT;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473                 {
2474                         // deluxemapping (light direction texture)
2475                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (r_glsl_deluxemapping.integer >= 2)
2484                 {
2485                         // fake deluxemapping (uniform light direction in tangentspace)
2486                         if (rsurface.uselightmaptexture)
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488                         else
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490                         permutation |= SHADERPERMUTATION_DIFFUSE;
2491                         if (specularscale > 0)
2492                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493                 }
2494                 else if (rsurface.uselightmaptexture)
2495                 {
2496                         // ordinary lightmapping (q1bsp, q3bsp)
2497                         mode = SHADERMODE_LIGHTMAP;
2498                 }
2499                 else
2500                 {
2501                         // ordinary vertex coloring (q3bsp)
2502                         mode = SHADERMODE_VERTEXCOLOR;
2503                 }
2504                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505                 {
2506                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507                         if (r_shadow_bouncegriddirectional)
2508                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509                 }
2510                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 // when using alphatocoverage, we don't need alphakill
2513                 if (vid.allowalphatocoverage)
2514                 {
2515                         if (r_transparent_alphatocoverage.integer)
2516                         {
2517                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2519                         }
2520                         else
2521                                 GL_AlphaToCoverage(false);
2522                 }
2523         }
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525                 colormod = dummy_colormod;
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530         switch(vid.renderpath)
2531         {
2532         case RENDERPATH_D3D9:
2533 #ifdef SUPPORTD3D
2534                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_LIGHTDIRECTION)
2546                         {
2547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2548                         }
2549                 }
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555
2556                 if (mode == SHADERMODE_LIGHTSOURCE)
2557                 {
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563
2564                         // additive passes are only darkened by fog, not tinted
2565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2567                 }
2568                 else
2569                 {
2570                         if (mode == SHADERMODE_FLATCOLOR)
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573                         }
2574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2583                         }
2584                         else
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2591                         }
2592                         // additive passes are only darkened by fog, not tinted
2593                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595                         else
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                         if (mode == SHADERMODE_WATER)
2606                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607                 }
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2612                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613                 if (rsurface.texture->pantstexture)
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615                 else
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617                 if (rsurface.texture->shirttexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630                         );
2631                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer)
2632                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2633                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2634
2635                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2636                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2637                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2638                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2643                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2645                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2647                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2648                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2649                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2650                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2651                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2652                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2653                 {
2654                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2655                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2656                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2657                 }
2658                 else
2659                 {
2660                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2661                 }
2662 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667                 {
2668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2669                         if (rsurface.rtlight)
2670                         {
2671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2673                         }
2674                 }
2675 #endif
2676                 break;
2677         case RENDERPATH_D3D10:
2678                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679                 break;
2680         case RENDERPATH_D3D11:
2681                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_GL20:
2684         case RENDERPATH_GLES2:
2685                 if (!vid.useinterleavedarrays)
2686                 {
2687                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2688                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2695                 }
2696                 else
2697                 {
2698                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2699                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700                 }
2701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703                 if (mode == SHADERMODE_LIGHTSOURCE)
2704                 {
2705                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2711         
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2716                 }
2717                 else
2718                 {
2719                         if (mode == SHADERMODE_FLATCOLOR)
2720                         {
2721                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722                         }
2723                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2724                         {
2725                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2726                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2727                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2730                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2731                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2732                         }
2733                         else
2734                         {
2735                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2736                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2737                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2740                         }
2741                         // additive passes are only darkened by fog, not tinted
2742                         if (r_glsl_permutation->loc_FogColor >= 0)
2743                         {
2744                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746                                 else
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         }
2749                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2750                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2751                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2752                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2753                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2754                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2757                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2758                 }
2759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2763                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2764
2765                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2767                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769                 {
2770                         if (rsurface.texture->pantstexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774                 }
2775                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776                 {
2777                         if (rsurface.texture->shirttexture)
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779                         else
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781                 }
2782                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2783                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791                         );
2792                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2793                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2794                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2795                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2796                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2797
2798                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2799                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2800                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2801                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2802                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2803                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2804                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2805                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2809                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2810                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2811                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2812                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2813                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2814                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2815                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2816                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2817                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2818                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2819                 {
2820                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2821                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2822                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2823                 }
2824                 else
2825                 {
2826                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2827                 }
2828                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2829                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2830                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2831                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2832                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833                 {
2834                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2835                         if (rsurface.rtlight)
2836                         {
2837                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2838                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2839                         }
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2842                 CHECKGLERROR
2843                 break;
2844         case RENDERPATH_GL11:
2845         case RENDERPATH_GL13:
2846         case RENDERPATH_GLES1:
2847                 break;
2848         case RENDERPATH_SOFT:
2849                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2850                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851                 R_SetupShader_SetPermutationSoft(mode, permutation);
2852                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853                 if (mode == SHADERMODE_LIGHTSOURCE)
2854                 {
2855                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861         
2862                         // additive passes are only darkened by fog, not tinted
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2865                 }
2866                 else
2867                 {
2868                         if (mode == SHADERMODE_FLATCOLOR)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871                         }
2872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2873                         {
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2881                         }
2882                         else
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2889                         }
2890                         // additive passes are only darkened by fog, not tinted
2891                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2896                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2897                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2898                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2899                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904                 }
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2910
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915                 {
2916                         if (rsurface.texture->pantstexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920                 }
2921                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922                 {
2923                         if (rsurface.texture->shirttexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927                 }
2928                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937                         );
2938                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2939                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2940
2941                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2942                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2943                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2944                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2945                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2946                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2949                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2950                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2951                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2952                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2953                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2954                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2955                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2956                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2957                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2958                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2959                 {
2960                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2961                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2962                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2963                 }
2964                 else
2965                 {
2966                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2967                 }
2968 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2969 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2970                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2971                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2972                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2973                 {
2974                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2975                         if (rsurface.rtlight)
2976                         {
2977                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2978                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2979                         }
2980                 }
2981                 break;
2982         }
2983 }
2984
2985 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2986 {
2987         // select a permutation of the lighting shader appropriate to this
2988         // combination of texture, entity, light source, and fogging, only use the
2989         // minimum features necessary to avoid wasting rendering time in the
2990         // fragment shader on features that are not being used
2991         unsigned int permutation = 0;
2992         unsigned int mode = 0;
2993         const float *lightcolorbase = rtlight->currentcolor;
2994         float ambientscale = rtlight->ambientscale;
2995         float diffusescale = rtlight->diffusescale;
2996         float specularscale = rtlight->specularscale;
2997         // this is the location of the light in view space
2998         vec3_t viewlightorigin;
2999         // this transforms from view space (camera) to light space (cubemap)
3000         matrix4x4_t viewtolight;
3001         matrix4x4_t lighttoview;
3002         float viewtolight16f[16];
3003         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3004         // light source
3005         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006         if (rtlight->currentcubemap != r_texture_whitecube)
3007                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008         if (diffusescale > 0)
3009                 permutation |= SHADERPERMUTATION_DIFFUSE;
3010         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012         if (r_shadow_usingshadowmap2d)
3013         {
3014                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015                 if (r_shadow_shadowmapvsdct)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017
3018                 if (r_shadow_shadowmapsampler)
3019                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3020                 if (r_shadow_shadowmappcf > 1)
3021                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3022                 else if (r_shadow_shadowmappcf)
3023                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3024         }
3025         if (vid.allowalphatocoverage)
3026                 GL_AlphaToCoverage(false);
3027         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3028         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3029         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3030         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3031         switch(vid.renderpath)
3032         {
3033         case RENDERPATH_D3D9:
3034 #ifdef SUPPORTD3D
3035                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3036                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3037                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3038                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3039                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3040                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3042                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3043                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3044                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3045                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3046
3047                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3048                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3049                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3050                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3051                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3052                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3053 #endif
3054                 break;
3055         case RENDERPATH_D3D10:
3056                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3057                 break;
3058         case RENDERPATH_D3D11:
3059                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3060                 break;
3061         case RENDERPATH_GL20:
3062         case RENDERPATH_GLES2:
3063                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3064                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3065                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3066                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3067                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3068                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3069                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3070                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3071                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3072                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3073                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3074
3075                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3076                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3077                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3078                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3079                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3080                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3081                 break;
3082         case RENDERPATH_GL11:
3083         case RENDERPATH_GL13:
3084         case RENDERPATH_GLES1:
3085                 break;
3086         case RENDERPATH_SOFT:
3087                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3088                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3089                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3090                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3091                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3092                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3093                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3094                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3095                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3096                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3097                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3098
3099                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3100                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3101                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3102                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3103                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3104                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3105                 break;
3106         }
3107 }
3108
3109 #define SKINFRAME_HASH 1024
3110
3111 typedef struct
3112 {
3113         int loadsequence; // incremented each level change
3114         memexpandablearray_t array;
3115         skinframe_t *hash[SKINFRAME_HASH];
3116 }
3117 r_skinframe_t;
3118 r_skinframe_t r_skinframe;
3119
3120 void R_SkinFrame_PrepareForPurge(void)
3121 {
3122         r_skinframe.loadsequence++;
3123         // wrap it without hitting zero
3124         if (r_skinframe.loadsequence >= 200)
3125                 r_skinframe.loadsequence = 1;
3126 }
3127
3128 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3129 {
3130         if (!skinframe)
3131                 return;
3132         // mark the skinframe as used for the purging code
3133         skinframe->loadsequence = r_skinframe.loadsequence;
3134 }
3135
3136 void R_SkinFrame_Purge(void)
3137 {
3138         int i;
3139         skinframe_t *s;
3140         for (i = 0;i < SKINFRAME_HASH;i++)
3141         {
3142                 for (s = r_skinframe.hash[i];s;s = s->next)
3143                 {
3144                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3145                         {
3146                                 if (s->merged == s->base)
3147                                         s->merged = NULL;
3148                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3149                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3150                                 R_PurgeTexture(s->merged);s->merged = NULL;
3151                                 R_PurgeTexture(s->base  );s->base   = NULL;
3152                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3153                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3154                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3155                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3156                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3157                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3158                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3159                                 s->loadsequence = 0;
3160                         }
3161                 }
3162         }
3163 }
3164
3165 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3166         skinframe_t *item;
3167         char basename[MAX_QPATH];
3168
3169         Image_StripImageExtension(name, basename, sizeof(basename));
3170
3171         if( last == NULL ) {
3172                 int hashindex;
3173                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3174                 item = r_skinframe.hash[hashindex];
3175         } else {
3176                 item = last->next;
3177         }
3178
3179         // linearly search through the hash bucket
3180         for( ; item ; item = item->next ) {
3181                 if( !strcmp( item->basename, basename ) ) {
3182                         return item;
3183                 }
3184         }
3185         return NULL;
3186 }
3187
3188 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3189 {
3190         skinframe_t *item;
3191         int hashindex;
3192         char basename[MAX_QPATH];
3193
3194         Image_StripImageExtension(name, basename, sizeof(basename));
3195
3196         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3197         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3198                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3199                         break;
3200
3201         if (!item) {
3202                 rtexture_t *dyntexture;
3203                 // check whether its a dynamic texture
3204                 dyntexture = CL_GetDynTexture( basename );
3205                 if (!add && !dyntexture)
3206                         return NULL;
3207                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3208                 memset(item, 0, sizeof(*item));
3209                 strlcpy(item->basename, basename, sizeof(item->basename));
3210                 item->base = dyntexture; // either NULL or dyntexture handle
3211                 item->textureflags = textureflags;
3212                 item->comparewidth = comparewidth;
3213                 item->compareheight = compareheight;
3214                 item->comparecrc = comparecrc;
3215                 item->next = r_skinframe.hash[hashindex];
3216                 r_skinframe.hash[hashindex] = item;
3217         }
3218         else if( item->base == NULL )
3219         {
3220                 rtexture_t *dyntexture;
3221                 // check whether its a dynamic texture
3222                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3223                 dyntexture = CL_GetDynTexture( basename );
3224                 item->base = dyntexture; // either NULL or dyntexture handle
3225         }
3226
3227         R_SkinFrame_MarkUsed(item);
3228         return item;
3229 }
3230
3231 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3232         { \
3233                 unsigned long long avgcolor[5], wsum; \
3234                 int pix, comp, w; \
3235                 avgcolor[0] = 0; \
3236                 avgcolor[1] = 0; \
3237                 avgcolor[2] = 0; \
3238                 avgcolor[3] = 0; \
3239                 avgcolor[4] = 0; \
3240                 wsum = 0; \
3241                 for(pix = 0; pix < cnt; ++pix) \
3242                 { \
3243                         w = 0; \
3244                         for(comp = 0; comp < 3; ++comp) \
3245                                 w += getpixel; \
3246                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3247                         { \
3248                                 ++wsum; \
3249                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3250                                 w = getpixel; \
3251                                 for(comp = 0; comp < 3; ++comp) \
3252                                         avgcolor[comp] += getpixel * w; \
3253                                 avgcolor[3] += w; \
3254                         } \
3255                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                         avgcolor[4] += getpixel; \
3257                 } \
3258                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3259                         avgcolor[3] = 1; \
3260                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3261                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3262                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3264         }
3265
3266 extern cvar_t gl_picmip;
3267 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3268 {
3269         int j;
3270         unsigned char *pixels;
3271         unsigned char *bumppixels;
3272         unsigned char *basepixels = NULL;
3273         int basepixels_width = 0;
3274         int basepixels_height = 0;
3275         skinframe_t *skinframe;
3276         rtexture_t *ddsbase = NULL;
3277         qboolean ddshasalpha = false;
3278         float ddsavgcolor[4];
3279         char basename[MAX_QPATH];
3280         int miplevel = R_PicmipForFlags(textureflags);
3281         int savemiplevel = miplevel;
3282         int mymiplevel;
3283
3284         if (cls.state == ca_dedicated)
3285                 return NULL;
3286
3287         // return an existing skinframe if already loaded
3288         // if loading of the first image fails, don't make a new skinframe as it
3289         // would cause all future lookups of this to be missing
3290         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3291         if (skinframe && skinframe->base)
3292                 return skinframe;
3293
3294         Image_StripImageExtension(name, basename, sizeof(basename));
3295
3296         // check for DDS texture file first
3297         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3298         {
3299                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3300                 if (basepixels == NULL)
3301                         return NULL;
3302         }
3303
3304         // FIXME handle miplevel
3305
3306         if (developer_loading.integer)
3307                 Con_Printf("loading skin \"%s\"\n", name);
3308
3309         // we've got some pixels to store, so really allocate this new texture now
3310         if (!skinframe)
3311                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3312         skinframe->stain = NULL;
3313         skinframe->merged = NULL;
3314         skinframe->base = NULL;
3315         skinframe->pants = NULL;
3316         skinframe->shirt = NULL;
3317         skinframe->nmap = NULL;
3318         skinframe->gloss = NULL;
3319         skinframe->glow = NULL;
3320         skinframe->fog = NULL;
3321         skinframe->reflect = NULL;
3322         skinframe->hasalpha = false;
3323
3324         if (ddsbase)
3325         {
3326                 skinframe->base = ddsbase;
3327                 skinframe->hasalpha = ddshasalpha;
3328                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3329                 if (r_loadfog && skinframe->hasalpha)
3330                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3331                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3332         }
3333         else
3334         {
3335                 basepixels_width = image_width;
3336                 basepixels_height = image_height;
3337                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3338                 if (textureflags & TEXF_ALPHA)
3339                 {
3340                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3341                         {
3342                                 if (basepixels[j] < 255)
3343                                 {
3344                                         skinframe->hasalpha = true;
3345                                         break;
3346                                 }
3347                         }
3348                         if (r_loadfog && skinframe->hasalpha)
3349                         {
3350                                 // has transparent pixels
3351                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3352                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3353                                 {
3354                                         pixels[j+0] = 255;
3355                                         pixels[j+1] = 255;
3356                                         pixels[j+2] = 255;
3357                                         pixels[j+3] = basepixels[j+3];
3358                                 }
3359                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3360                                 Mem_Free(pixels);
3361                         }
3362                 }
3363                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3364 #ifndef USE_GLES2
3365                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3366                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3367                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3368                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3369                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3370 #endif
3371         }
3372
3373         if (r_loaddds)
3374         {
3375                 mymiplevel = savemiplevel;
3376                 if (r_loadnormalmap)
3377                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3378                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3379                 if (r_loadgloss)
3380                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3381                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3383                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384         }
3385
3386         // _norm is the name used by tenebrae and has been adopted as standard
3387         if (r_loadnormalmap && skinframe->nmap == NULL)
3388         {
3389                 mymiplevel = savemiplevel;
3390                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3391                 {
3392                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3393                         Mem_Free(pixels);
3394                         pixels = NULL;
3395                 }
3396                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3397                 {
3398                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3399                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3400                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3401                         Mem_Free(pixels);
3402                         Mem_Free(bumppixels);
3403                 }
3404                 else if (r_shadow_bumpscale_basetexture.value > 0)
3405                 {
3406                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3407                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3408                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3409                         Mem_Free(pixels);
3410                 }
3411 #ifndef USE_GLES2
3412                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3413                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3414 #endif
3415         }
3416
3417         // _luma is supported only for tenebrae compatibility
3418         // _glow is the preferred name
3419         mymiplevel = savemiplevel;
3420         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3421         {
3422                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3423 #ifndef USE_GLES2
3424                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3425                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3426 #endif
3427                 Mem_Free(pixels);pixels = NULL;
3428         }
3429
3430         mymiplevel = savemiplevel;
3431         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3432         {
3433                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3436                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438                 Mem_Free(pixels);
3439                 pixels = NULL;
3440         }
3441
3442         mymiplevel = savemiplevel;
3443         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3444         {
3445                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3446 #ifndef USE_GLES2
3447                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3448                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3449 #endif
3450                 Mem_Free(pixels);
3451                 pixels = NULL;
3452         }
3453
3454         mymiplevel = savemiplevel;
3455         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3456         {
3457                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3458 #ifndef USE_GLES2
3459                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3460                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3461 #endif
3462                 Mem_Free(pixels);
3463                 pixels = NULL;
3464         }
3465
3466         mymiplevel = savemiplevel;
3467         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3468         {
3469                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3470 #ifndef USE_GLES2
3471                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3472                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3473 #endif
3474                 Mem_Free(pixels);
3475                 pixels = NULL;
3476         }
3477
3478         if (basepixels)
3479                 Mem_Free(basepixels);
3480
3481         return skinframe;
3482 }
3483
3484 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3485 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3486 {
3487         int i;
3488         unsigned char *temp1, *temp2;
3489         skinframe_t *skinframe;
3490
3491         if (cls.state == ca_dedicated)
3492                 return NULL;
3493
3494         // if already loaded just return it, otherwise make a new skinframe
3495         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3496         if (skinframe && skinframe->base)
3497                 return skinframe;
3498
3499         skinframe->stain = NULL;
3500         skinframe->merged = NULL;
3501         skinframe->base = NULL;
3502         skinframe->pants = NULL;
3503         skinframe->shirt = NULL;
3504         skinframe->nmap = NULL;
3505         skinframe->gloss = NULL;
3506         skinframe->glow = NULL;
3507         skinframe->fog = NULL;
3508         skinframe->reflect = NULL;
3509         skinframe->hasalpha = false;
3510
3511         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3512         if (!skindata)
3513                 return NULL;
3514
3515         if (developer_loading.integer)
3516                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3517
3518         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3519         {
3520                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3521                 temp2 = temp1 + width * height * 4;
3522                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3523                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3524                 Mem_Free(temp1);
3525         }
3526         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3527         if (textureflags & TEXF_ALPHA)
3528         {
3529                 for (i = 3;i < width * height * 4;i += 4)
3530                 {
3531                         if (skindata[i] < 255)
3532                         {
3533                                 skinframe->hasalpha = true;
3534                                 break;
3535                         }
3536                 }
3537                 if (r_loadfog && skinframe->hasalpha)
3538                 {
3539                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3540                         memcpy(fogpixels, skindata, width * height * 4);
3541                         for (i = 0;i < width * height * 4;i += 4)
3542                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3543                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3544                         Mem_Free(fogpixels);
3545                 }
3546         }
3547
3548         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3549         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3550
3551         return skinframe;
3552 }
3553
3554 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3555 {
3556         int i;
3557         int featuresmask;
3558         skinframe_t *skinframe;
3559
3560         if (cls.state == ca_dedicated)
3561                 return NULL;
3562
3563         // if already loaded just return it, otherwise make a new skinframe
3564         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3565         if (skinframe && skinframe->base)
3566                 return skinframe;
3567
3568         skinframe->stain = NULL;
3569         skinframe->merged = NULL;
3570         skinframe->base = NULL;
3571         skinframe->pants = NULL;
3572         skinframe->shirt = NULL;
3573         skinframe->nmap = NULL;
3574         skinframe->gloss = NULL;
3575         skinframe->glow = NULL;
3576         skinframe->fog = NULL;
3577         skinframe->reflect = NULL;
3578         skinframe->hasalpha = false;
3579
3580         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3581         if (!skindata)
3582                 return NULL;
3583
3584         if (developer_loading.integer)
3585                 Con_Printf("loading quake skin \"%s\"\n", name);
3586
3587         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3588         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3589         memcpy(skinframe->qpixels, skindata, width*height);
3590         skinframe->qwidth = width;
3591         skinframe->qheight = height;
3592
3593         featuresmask = 0;
3594         for (i = 0;i < width * height;i++)
3595                 featuresmask |= palette_featureflags[skindata[i]];
3596
3597         skinframe->hasalpha = false;
3598         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3599         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3600         skinframe->qgeneratemerged = true;
3601         skinframe->qgeneratebase = skinframe->qhascolormapping;
3602         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3603
3604         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3605         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3606
3607         return skinframe;
3608 }
3609
3610 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3611 {
3612         int width;
3613         int height;
3614         unsigned char *skindata;
3615
3616         if (!skinframe->qpixels)
3617                 return;
3618
3619         if (!skinframe->qhascolormapping)
3620                 colormapped = false;
3621
3622         if (colormapped)
3623         {
3624                 if (!skinframe->qgeneratebase)
3625                         return;
3626         }
3627         else
3628         {
3629                 if (!skinframe->qgeneratemerged)
3630                         return;
3631         }
3632
3633         width = skinframe->qwidth;
3634         height = skinframe->qheight;
3635         skindata = skinframe->qpixels;
3636
3637         if (skinframe->qgeneratenmap)
3638         {
3639                 unsigned char *temp1, *temp2;
3640                 skinframe->qgeneratenmap = false;
3641                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3642                 temp2 = temp1 + width * height * 4;
3643                 // use either a custom palette or the quake palette
3644                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3645                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3646                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3647                 Mem_Free(temp1);
3648         }
3649
3650         if (skinframe->qgenerateglow)
3651         {
3652                 skinframe->qgenerateglow = false;
3653                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3654         }
3655
3656         if (colormapped)
3657         {
3658                 skinframe->qgeneratebase = false;
3659                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3660                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3661                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3662         }
3663         else
3664         {
3665                 skinframe->qgeneratemerged = false;
3666                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3667         }
3668
3669         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3670         {
3671                 Mem_Free(skinframe->qpixels);
3672                 skinframe->qpixels = NULL;
3673         }
3674 }
3675
3676 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3677 {
3678         int i;
3679         skinframe_t *skinframe;
3680
3681         if (cls.state == ca_dedicated)
3682                 return NULL;
3683
3684         // if already loaded just return it, otherwise make a new skinframe
3685         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3686         if (skinframe && skinframe->base)
3687                 return skinframe;
3688
3689         skinframe->stain = NULL;
3690         skinframe->merged = NULL;
3691         skinframe->base = NULL;
3692         skinframe->pants = NULL;
3693         skinframe->shirt = NULL;
3694         skinframe->nmap = NULL;
3695         skinframe->gloss = NULL;
3696         skinframe->glow = NULL;
3697         skinframe->fog = NULL;
3698         skinframe->reflect = NULL;
3699         skinframe->hasalpha = false;
3700
3701         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3702         if (!skindata)
3703                 return NULL;
3704
3705         if (developer_loading.integer)
3706                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3707
3708         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3709         if (textureflags & TEXF_ALPHA)
3710         {
3711                 for (i = 0;i < width * height;i++)
3712                 {
3713                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3714                         {
3715                                 skinframe->hasalpha = true;
3716                                 break;
3717                         }
3718                 }
3719                 if (r_loadfog && skinframe->hasalpha)
3720                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3721         }
3722
3723         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3724         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3725
3726         return skinframe;
3727 }
3728
3729 skinframe_t *R_SkinFrame_LoadMissing(void)
3730 {
3731         skinframe_t *skinframe;
3732
3733         if (cls.state == ca_dedicated)
3734                 return NULL;
3735
3736         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3737         skinframe->stain = NULL;
3738         skinframe->merged = NULL;
3739         skinframe->base = NULL;
3740         skinframe->pants = NULL;
3741         skinframe->shirt = NULL;
3742         skinframe->nmap = NULL;
3743         skinframe->gloss = NULL;
3744         skinframe->glow = NULL;
3745         skinframe->fog = NULL;
3746         skinframe->reflect = NULL;
3747         skinframe->hasalpha = false;
3748
3749         skinframe->avgcolor[0] = rand() / RAND_MAX;
3750         skinframe->avgcolor[1] = rand() / RAND_MAX;
3751         skinframe->avgcolor[2] = rand() / RAND_MAX;
3752         skinframe->avgcolor[3] = 1;
3753
3754         return skinframe;
3755 }
3756
3757 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3758 typedef struct suffixinfo_s
3759 {
3760         const char *suffix;
3761         qboolean flipx, flipy, flipdiagonal;
3762 }
3763 suffixinfo_t;
3764 static suffixinfo_t suffix[3][6] =
3765 {
3766         {
3767                 {"px",   false, false, false},
3768                 {"nx",   false, false, false},
3769                 {"py",   false, false, false},
3770                 {"ny",   false, false, false},
3771                 {"pz",   false, false, false},
3772                 {"nz",   false, false, false}
3773         },
3774         {
3775                 {"posx", false, false, false},
3776                 {"negx", false, false, false},
3777                 {"posy", false, false, false},
3778                 {"negy", false, false, false},
3779                 {"posz", false, false, false},
3780                 {"negz", false, false, false}
3781         },
3782         {
3783                 {"rt",    true, false,  true},
3784                 {"lf",   false,  true,  true},
3785                 {"ft",    true,  true, false},
3786                 {"bk",   false, false, false},
3787                 {"up",    true, false,  true},
3788                 {"dn",    true, false,  true}
3789         }
3790 };
3791
3792 static int componentorder[4] = {0, 1, 2, 3};
3793
3794 rtexture_t *R_LoadCubemap(const char *basename)
3795 {
3796         int i, j, cubemapsize;
3797         unsigned char *cubemappixels, *image_buffer;
3798         rtexture_t *cubemaptexture;
3799         char name[256];
3800         // must start 0 so the first loadimagepixels has no requested width/height
3801         cubemapsize = 0;
3802         cubemappixels = NULL;
3803         cubemaptexture = NULL;
3804         // keep trying different suffix groups (posx, px, rt) until one loads
3805         for (j = 0;j < 3 && !cubemappixels;j++)
3806         {
3807                 // load the 6 images in the suffix group
3808                 for (i = 0;i < 6;i++)
3809                 {
3810                         // generate an image name based on the base and and suffix
3811                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3812                         // load it
3813                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3814                         {
3815                                 // an image loaded, make sure width and height are equal
3816                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3817                                 {
3818                                         // if this is the first image to load successfully, allocate the cubemap memory
3819                                         if (!cubemappixels && image_width >= 1)
3820                                         {
3821                                                 cubemapsize = image_width;
3822                                                 // note this clears to black, so unavailable sides are black
3823                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3824                                         }
3825                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3826                                         if (cubemappixels)
3827                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3828                                 }
3829                                 else
3830                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3831                                 // free the image
3832                                 Mem_Free(image_buffer);
3833                         }
3834                 }
3835         }
3836         // if a cubemap loaded, upload it
3837         if (cubemappixels)
3838         {
3839                 if (developer_loading.integer)
3840                         Con_Printf("loading cubemap \"%s\"\n", basename);
3841
3842                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3843                 Mem_Free(cubemappixels);
3844         }
3845         else
3846         {
3847                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3848                 if (developer_loading.integer)
3849                 {
3850                         Con_Printf("(tried tried images ");
3851                         for (j = 0;j < 3;j++)
3852                                 for (i = 0;i < 6;i++)
3853                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3854                         Con_Print(" and was unable to find any of them).\n");
3855                 }
3856         }
3857         return cubemaptexture;
3858 }
3859
3860 rtexture_t *R_GetCubemap(const char *basename)
3861 {
3862         int i;
3863         for (i = 0;i < r_texture_numcubemaps;i++)
3864                 if (r_texture_cubemaps[i] != NULL)
3865                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3866                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3867         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3868                 return r_texture_whitecube;
3869         r_texture_numcubemaps++;
3870         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3871         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3872         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3873         return r_texture_cubemaps[i]->texture;
3874 }
3875
3876 void R_FreeCubemap(const char *basename)
3877 {
3878         int i;
3879
3880         for (i = 0;i < r_texture_numcubemaps;i++)
3881         {
3882                 if (r_texture_cubemaps[i] != NULL)
3883                 {
3884                         if (r_texture_cubemaps[i]->texture)
3885                         {
3886                                 if (developer_loading.integer)
3887                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3888                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3889                                 Mem_Free(r_texture_cubemaps[i]);
3890                                 r_texture_cubemaps[i] = NULL;
3891                         }
3892                 }
3893         }
3894 }
3895
3896 void R_FreeCubemaps(void)
3897 {
3898         int i;
3899         for (i = 0;i < r_texture_numcubemaps;i++)
3900         {
3901                 if (developer_loading.integer)
3902                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3903                 if (r_texture_cubemaps[i] != NULL)
3904                 {
3905                         if (r_texture_cubemaps[i]->texture)
3906                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3907                         Mem_Free(r_texture_cubemaps[i]);
3908                 }
3909         }
3910         r_texture_numcubemaps = 0;
3911 }
3912
3913 void R_Main_FreeViewCache(void)
3914 {
3915         if (r_refdef.viewcache.entityvisible)
3916                 Mem_Free(r_refdef.viewcache.entityvisible);
3917         if (r_refdef.viewcache.world_pvsbits)
3918                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3919         if (r_refdef.viewcache.world_leafvisible)
3920                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3921         if (r_refdef.viewcache.world_surfacevisible)
3922                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3923         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3924 }
3925
3926 void R_Main_ResizeViewCache(void)
3927 {
3928         int numentities = r_refdef.scene.numentities;
3929         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3930         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3931         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3932         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3933         if (r_refdef.viewcache.maxentities < numentities)
3934         {
3935                 r_refdef.viewcache.maxentities = numentities;
3936                 if (r_refdef.viewcache.entityvisible)
3937                         Mem_Free(r_refdef.viewcache.entityvisible);
3938                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3939         }
3940         if (r_refdef.viewcache.world_numclusters != numclusters)
3941         {
3942                 r_refdef.viewcache.world_numclusters = numclusters;
3943                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3944                 if (r_refdef.viewcache.world_pvsbits)
3945                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3946                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3947         }
3948         if (r_refdef.viewcache.world_numleafs != numleafs)
3949         {
3950                 r_refdef.viewcache.world_numleafs = numleafs;
3951                 if (r_refdef.viewcache.world_leafvisible)
3952                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3953                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3954         }
3955         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3956         {
3957                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3958                 if (r_refdef.viewcache.world_surfacevisible)
3959                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3960                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3961         }
3962 }
3963
3964 extern rtexture_t *loadingscreentexture;
3965 void gl_main_start(void)
3966 {
3967         loadingscreentexture = NULL;
3968         r_texture_blanknormalmap = NULL;
3969         r_texture_white = NULL;
3970         r_texture_grey128 = NULL;
3971         r_texture_black = NULL;
3972         r_texture_whitecube = NULL;
3973         r_texture_normalizationcube = NULL;
3974         r_texture_fogattenuation = NULL;
3975         r_texture_fogheighttexture = NULL;
3976         r_texture_gammaramps = NULL;
3977         r_texture_numcubemaps = 0;
3978
3979         r_loaddds = r_texture_dds_load.integer != 0;
3980         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3981
3982         switch(vid.renderpath)
3983         {
3984         case RENDERPATH_GL20:
3985         case RENDERPATH_D3D9:
3986         case RENDERPATH_D3D10:
3987         case RENDERPATH_D3D11:
3988         case RENDERPATH_SOFT:
3989         case RENDERPATH_GLES2:
3990                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991                 Cvar_SetValueQuick(&gl_combine, 1);
3992                 Cvar_SetValueQuick(&r_glsl, 1);
3993                 r_loadnormalmap = true;
3994                 r_loadgloss = true;
3995                 r_loadfog = false;
3996                 break;
3997         case RENDERPATH_GL13:
3998         case RENDERPATH_GLES1:
3999                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4000                 Cvar_SetValueQuick(&gl_combine, 1);
4001                 Cvar_SetValueQuick(&r_glsl, 0);
4002                 r_loadnormalmap = false;
4003                 r_loadgloss = false;
4004                 r_loadfog = true;
4005                 break;
4006         case RENDERPATH_GL11:
4007                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4008                 Cvar_SetValueQuick(&gl_combine, 0);
4009                 Cvar_SetValueQuick(&r_glsl, 0);
4010                 r_loadnormalmap = false;
4011                 r_loadgloss = false;
4012                 r_loadfog = true;
4013                 break;
4014         }
4015
4016         R_AnimCache_Free();
4017         R_FrameData_Reset();
4018
4019         r_numqueries = 0;
4020         r_maxqueries = 0;
4021         memset(r_queries, 0, sizeof(r_queries));
4022
4023         r_qwskincache = NULL;
4024         r_qwskincache_size = 0;
4025
4026         // due to caching of texture_t references, the collision cache must be reset
4027         Collision_Cache_Reset(true);
4028
4029         // set up r_skinframe loading system for textures
4030         memset(&r_skinframe, 0, sizeof(r_skinframe));
4031         r_skinframe.loadsequence = 1;
4032         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4033
4034         r_main_texturepool = R_AllocTexturePool();
4035         R_BuildBlankTextures();
4036         R_BuildNoTexture();
4037         if (vid.support.arb_texture_cube_map)
4038         {
4039                 R_BuildWhiteCube();
4040                 R_BuildNormalizationCube();
4041         }
4042         r_texture_fogattenuation = NULL;
4043         r_texture_fogheighttexture = NULL;
4044         r_texture_gammaramps = NULL;
4045         //r_texture_fogintensity = NULL;
4046         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4047         memset(&r_waterstate, 0, sizeof(r_waterstate));
4048         r_glsl_permutation = NULL;
4049         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4050         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4051         glslshaderstring = NULL;
4052 #ifdef SUPPORTD3D
4053         r_hlsl_permutation = NULL;
4054         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4055         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4056 #endif
4057         hlslshaderstring = NULL;
4058         memset(&r_svbsp, 0, sizeof (r_svbsp));
4059
4060         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4061         r_texture_numcubemaps = 0;
4062
4063         r_refdef.fogmasktable_density = 0;
4064 }
4065
4066 void gl_main_shutdown(void)
4067 {
4068         R_AnimCache_Free();
4069         R_FrameData_Reset();
4070
4071         R_Main_FreeViewCache();
4072
4073         switch(vid.renderpath)
4074         {
4075         case RENDERPATH_GL11:
4076         case RENDERPATH_GL13:
4077         case RENDERPATH_GL20:
4078         case RENDERPATH_GLES1:
4079         case RENDERPATH_GLES2:
4080 #ifdef GL_SAMPLES_PASSED_ARB
4081                 if (r_maxqueries)
4082                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4083 #endif
4084                 break;
4085         case RENDERPATH_D3D9:
4086                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087                 break;
4088         case RENDERPATH_D3D10:
4089                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090                 break;
4091         case RENDERPATH_D3D11:
4092                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4093                 break;
4094         case RENDERPATH_SOFT:
4095                 break;
4096         }
4097
4098         r_numqueries = 0;
4099         r_maxqueries = 0;
4100         memset(r_queries, 0, sizeof(r_queries));
4101
4102         r_qwskincache = NULL;
4103         r_qwskincache_size = 0;
4104
4105         // clear out the r_skinframe state
4106         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4107         memset(&r_skinframe, 0, sizeof(r_skinframe));
4108
4109         if (r_svbsp.nodes)
4110                 Mem_Free(r_svbsp.nodes);
4111         memset(&r_svbsp, 0, sizeof (r_svbsp));
4112         R_FreeTexturePool(&r_main_texturepool);
4113         loadingscreentexture = NULL;
4114         r_texture_blanknormalmap = NULL;
4115         r_texture_white = NULL;
4116         r_texture_grey128 = NULL;
4117         r_texture_black = NULL;
4118         r_texture_whitecube = NULL;
4119         r_texture_normalizationcube = NULL;
4120         r_texture_fogattenuation = NULL;
4121         r_texture_fogheighttexture = NULL;
4122         r_texture_gammaramps = NULL;
4123         r_texture_numcubemaps = 0;
4124         //r_texture_fogintensity = NULL;
4125         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4126         memset(&r_waterstate, 0, sizeof(r_waterstate));
4127         R_GLSL_Restart_f();
4128
4129         r_glsl_permutation = NULL;
4130         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4131         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4132         glslshaderstring = NULL;
4133 #ifdef SUPPORTD3D
4134         r_hlsl_permutation = NULL;
4135         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4136         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4137 #endif
4138         hlslshaderstring = NULL;
4139 }
4140
4141 extern void CL_ParseEntityLump(char *entitystring);
4142 void gl_main_newmap(void)
4143 {
4144         // FIXME: move this code to client
4145         char *entities, entname[MAX_QPATH];
4146         if (r_qwskincache)
4147                 Mem_Free(r_qwskincache);
4148         r_qwskincache = NULL;
4149         r_qwskincache_size = 0;
4150         if (cl.worldmodel)
4151         {
4152                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4153                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4154                 {
4155                         CL_ParseEntityLump(entities);
4156                         Mem_Free(entities);
4157                         return;
4158                 }
4159                 if (cl.worldmodel->brush.entities)
4160                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4161         }
4162         R_Main_FreeViewCache();
4163
4164         R_FrameData_Reset();
4165 }
4166
4167 void GL_Main_Init(void)
4168 {
4169         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4170
4171         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4172         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4173         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4174         if (gamemode == GAME_NEHAHRA)
4175         {
4176                 Cvar_RegisterVariable (&gl_fogenable);
4177                 Cvar_RegisterVariable (&gl_fogdensity);
4178                 Cvar_RegisterVariable (&gl_fogred);
4179                 Cvar_RegisterVariable (&gl_foggreen);
4180                 Cvar_RegisterVariable (&gl_fogblue);
4181                 Cvar_RegisterVariable (&gl_fogstart);
4182                 Cvar_RegisterVariable (&gl_fogend);
4183                 Cvar_RegisterVariable (&gl_skyclip);
4184         }
4185         Cvar_RegisterVariable(&r_motionblur);
4186         Cvar_RegisterVariable(&r_damageblur);
4187         Cvar_RegisterVariable(&r_motionblur_averaging);
4188         Cvar_RegisterVariable(&r_motionblur_randomize);
4189         Cvar_RegisterVariable(&r_motionblur_minblur);
4190         Cvar_RegisterVariable(&r_motionblur_maxblur);
4191         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4192         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4193         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4194         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4195         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4196         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4197         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4198         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4199         Cvar_RegisterVariable(&r_equalize_entities_by);
4200         Cvar_RegisterVariable(&r_equalize_entities_to);
4201         Cvar_RegisterVariable(&r_depthfirst);
4202         Cvar_RegisterVariable(&r_useinfinitefarclip);
4203         Cvar_RegisterVariable(&r_farclip_base);
4204         Cvar_RegisterVariable(&r_farclip_world);
4205         Cvar_RegisterVariable(&r_nearclip);
4206         Cvar_RegisterVariable(&r_deformvertexes);
4207         Cvar_RegisterVariable(&r_transparent);
4208         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4209         Cvar_RegisterVariable(&r_showoverdraw);
4210         Cvar_RegisterVariable(&r_showbboxes);
4211         Cvar_RegisterVariable(&r_showsurfaces);
4212         Cvar_RegisterVariable(&r_showtris);
4213         Cvar_RegisterVariable(&r_shownormals);
4214         Cvar_RegisterVariable(&r_showlighting);
4215         Cvar_RegisterVariable(&r_showshadowvolumes);
4216         Cvar_RegisterVariable(&r_showcollisionbrushes);
4217         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4218         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4219         Cvar_RegisterVariable(&r_showdisabledepthtest);
4220         Cvar_RegisterVariable(&r_drawportals);
4221         Cvar_RegisterVariable(&r_drawentities);
4222         Cvar_RegisterVariable(&r_draw2d);
4223         Cvar_RegisterVariable(&r_drawworld);
4224         Cvar_RegisterVariable(&r_cullentities_trace);
4225         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4226         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4227         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4228         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4229         Cvar_RegisterVariable(&r_sortentities);
4230         Cvar_RegisterVariable(&r_drawviewmodel);
4231         Cvar_RegisterVariable(&r_drawexteriormodel);
4232         Cvar_RegisterVariable(&r_speeds);
4233         Cvar_RegisterVariable(&r_fullbrights);
4234         Cvar_RegisterVariable(&r_wateralpha);
4235         Cvar_RegisterVariable(&r_dynamic);
4236         Cvar_RegisterVariable(&r_fakelight);
4237         Cvar_RegisterVariable(&r_fakelight_intensity);
4238         Cvar_RegisterVariable(&r_fullbright);
4239         Cvar_RegisterVariable(&r_shadows);
4240         Cvar_RegisterVariable(&r_shadows_darken);
4241         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4242         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4243         Cvar_RegisterVariable(&r_shadows_throwdistance);
4244         Cvar_RegisterVariable(&r_shadows_throwdirection);
4245         Cvar_RegisterVariable(&r_shadows_focus);
4246         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4247         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4248         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4249         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4250         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4251         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4252         Cvar_RegisterVariable(&r_fog_exp2);
4253         Cvar_RegisterVariable(&r_fog_clear);
4254         Cvar_RegisterVariable(&r_drawfog);
4255         Cvar_RegisterVariable(&r_transparentdepthmasking);
4256         Cvar_RegisterVariable(&r_transparent_sortmindist);
4257         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4258         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4259         Cvar_RegisterVariable(&r_texture_dds_load);
4260         Cvar_RegisterVariable(&r_texture_dds_save);
4261         Cvar_RegisterVariable(&r_textureunits);
4262         Cvar_RegisterVariable(&gl_combine);
4263         Cvar_RegisterVariable(&r_viewfbo);
4264         Cvar_RegisterVariable(&r_viewscale);
4265         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4266         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4267         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4271         Cvar_RegisterVariable(&r_glsl);
4272         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4273         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4274         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4275         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4281         Cvar_RegisterVariable(&r_glsl_postprocess);
4282         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4283         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4284         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4290
4291         Cvar_RegisterVariable(&r_water);
4292         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4293         Cvar_RegisterVariable(&r_water_clippingplanebias);
4294         Cvar_RegisterVariable(&r_water_refractdistort);
4295         Cvar_RegisterVariable(&r_water_reflectdistort);
4296         Cvar_RegisterVariable(&r_water_scissormode);
4297         Cvar_RegisterVariable(&r_water_lowquality);
4298
4299         Cvar_RegisterVariable(&r_lerpsprites);
4300         Cvar_RegisterVariable(&r_lerpmodels);
4301         Cvar_RegisterVariable(&r_lerplightstyles);
4302         Cvar_RegisterVariable(&r_waterscroll);
4303         Cvar_RegisterVariable(&r_bloom);
4304         Cvar_RegisterVariable(&r_bloom_colorscale);
4305         Cvar_RegisterVariable(&r_bloom_brighten);
4306         Cvar_RegisterVariable(&r_bloom_blur);
4307         Cvar_RegisterVariable(&r_bloom_resolution);
4308         Cvar_RegisterVariable(&r_bloom_colorexponent);
4309         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4310         Cvar_RegisterVariable(&r_hdr);
4311         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4312         Cvar_RegisterVariable(&r_hdr_glowintensity);
4313         Cvar_RegisterVariable(&r_hdr_range);
4314         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4315         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4316         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4317         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4321         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4322         Cvar_RegisterVariable(&developer_texturelogging);
4323         Cvar_RegisterVariable(&gl_lightmaps);
4324         Cvar_RegisterVariable(&r_test);
4325         Cvar_RegisterVariable(&r_glsl_saturation);
4326         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4327         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4328         Cvar_RegisterVariable(&r_framedatasize);
4329         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4330                 Cvar_SetValue("r_fullbrights", 0);
4331         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4332 }
4333
4334 extern void R_Textures_Init(void);
4335 extern void GL_Draw_Init(void);
4336 extern void GL_Main_Init(void);
4337 extern void R_Shadow_Init(void);
4338 extern void R_Sky_Init(void);
4339 extern void GL_Surf_Init(void);
4340 extern void R_Particles_Init(void);
4341 extern void R_Explosion_Init(void);
4342 extern void gl_backend_init(void);
4343 extern void Sbar_Init(void);
4344 extern void R_LightningBeams_Init(void);
4345 extern void Mod_RenderInit(void);
4346 extern void Font_Init(void);
4347
4348 void Render_Init(void)
4349 {
4350         gl_backend_init();
4351         R_Textures_Init();
4352         GL_Main_Init();
4353         Font_Init();
4354         GL_Draw_Init();
4355         R_Shadow_Init();
4356         R_Sky_Init();
4357         GL_Surf_Init();
4358         Sbar_Init();
4359         R_Particles_Init();
4360         R_Explosion_Init();
4361         R_LightningBeams_Init();
4362         Mod_RenderInit();
4363 }
4364
4365 /*
4366 ===============
4367 GL_Init
4368 ===============
4369 */
4370 #ifndef USE_GLES2
4371 extern char *ENGINE_EXTENSIONS;
4372 void GL_Init (void)
4373 {
4374         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4375         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4376         gl_version = (const char *)qglGetString(GL_VERSION);
4377         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4378
4379         if (!gl_extensions)
4380                 gl_extensions = "";
4381         if (!gl_platformextensions)
4382                 gl_platformextensions = "";
4383
4384         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4385         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4386         Con_Printf("GL_VERSION: %s\n", gl_version);
4387         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4388         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4389
4390         VID_CheckExtensions();
4391
4392         // LordHavoc: report supported extensions
4393         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4394
4395         // clear to black (loading plaque will be seen over this)
4396         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4397 }
4398 #endif
4399
4400 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4401 {
4402         int i;
4403         mplane_t *p;
4404         if (r_trippy.integer)
4405                 return false;
4406         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4407         {
4408                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4409                 if (i == 4)
4410                         continue;
4411                 p = r_refdef.view.frustum + i;
4412                 switch(p->signbits)
4413                 {
4414                 default:
4415                 case 0:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 1:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 2:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 3:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 4:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 5:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 6:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 7:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 }
4448         }
4449         return false;
4450 }
4451
4452 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4453 {
4454         int i;
4455         const mplane_t *p;
4456         if (r_trippy.integer)
4457                 return false;
4458         for (i = 0;i < numplanes;i++)
4459         {
4460                 p = planes + i;
4461                 switch(p->signbits)
4462                 {
4463                 default:
4464                 case 0:
4465                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 1:
4469                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 2:
4473                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 3:
4477                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 4:
4481                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 case 5:
4485                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4486                                 return true;
4487                         break;
4488                 case 6:
4489                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4490                                 return true;
4491                         break;
4492                 case 7:
4493                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 }
4497         }
4498         return false;
4499 }
4500
4501 //==================================================================================
4502
4503 // LordHavoc: this stores temporary data used within the same frame
4504
4505 typedef struct r_framedata_mem_s
4506 {
4507         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4508         size_t size; // how much usable space
4509         size_t current; // how much space in use
4510         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4511         size_t wantedsize; // how much space was allocated
4512         unsigned char *data; // start of real data (16byte aligned)
4513 }
4514 r_framedata_mem_t;
4515
4516 static r_framedata_mem_t *r_framedata_mem;
4517
4518 void R_FrameData_Reset(void)
4519 {
4520         while (r_framedata_mem)
4521         {
4522                 r_framedata_mem_t *next = r_framedata_mem->purge;
4523                 Mem_Free(r_framedata_mem);
4524                 r_framedata_mem = next;
4525         }
4526 }
4527
4528 void R_FrameData_Resize(void)
4529 {
4530         size_t wantedsize;
4531         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4532         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4533         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4534         {
4535                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4536                 newmem->wantedsize = wantedsize;
4537                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4538                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4539                 newmem->current = 0;
4540                 newmem->mark = 0;
4541                 newmem->purge = r_framedata_mem;
4542                 r_framedata_mem = newmem;
4543         }
4544 }
4545
4546 void R_FrameData_NewFrame(void)
4547 {
4548         R_FrameData_Resize();
4549         if (!r_framedata_mem)
4550                 return;
4551         // if we ran out of space on the last frame, free the old memory now
4552         while (r_framedata_mem->purge)
4553         {
4554                 // repeatedly remove the second item in the list, leaving only head
4555                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4556                 Mem_Free(r_framedata_mem->purge);
4557                 r_framedata_mem->purge = next;
4558         }
4559         // reset the current mem pointer
4560         r_framedata_mem->current = 0;
4561         r_framedata_mem->mark = 0;
4562 }
4563
4564 void *R_FrameData_Alloc(size_t size)
4565 {
4566         void *data;
4567
4568         // align to 16 byte boundary - the data pointer is already aligned, so we
4569         // only need to ensure the size of every allocation is also aligned
4570         size = (size + 15) & ~15;
4571
4572         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4573         {
4574                 // emergency - we ran out of space, allocate more memory
4575                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4576                 R_FrameData_Resize();
4577         }
4578
4579         data = r_framedata_mem->data + r_framedata_mem->current;
4580         r_framedata_mem->current += size;
4581
4582         // count the usage for stats
4583         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4584         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4585
4586         return (void *)data;
4587 }
4588
4589 void *R_FrameData_Store(size_t size, void *data)
4590 {
4591         void *d = R_FrameData_Alloc(size);
4592         if (d && data)
4593                 memcpy(d, data, size);
4594         return d;
4595 }
4596
4597 void R_FrameData_SetMark(void)
4598 {
4599         if (!r_framedata_mem)
4600                 return;
4601         r_framedata_mem->mark = r_framedata_mem->current;
4602 }
4603
4604 void R_FrameData_ReturnToMark(void)
4605 {
4606         if (!r_framedata_mem)
4607                 return;
4608         r_framedata_mem->current = r_framedata_mem->mark;
4609 }
4610
4611 //==================================================================================
4612
4613 // LordHavoc: animcache originally written by Echon, rewritten since then
4614
4615 /**
4616  * Animation cache prevents re-generating mesh data for an animated model
4617  * multiple times in one frame for lighting, shadowing, reflections, etc.
4618  */
4619
4620 void R_AnimCache_Free(void)
4621 {
4622 }
4623
4624 void R_AnimCache_ClearCache(void)
4625 {
4626         int i;
4627         entity_render_t *ent;
4628
4629         for (i = 0;i < r_refdef.scene.numentities;i++)
4630         {
4631                 ent = r_refdef.scene.entities[i];
4632                 ent->animcache_vertex3f = NULL;
4633                 ent->animcache_normal3f = NULL;
4634                 ent->animcache_svector3f = NULL;
4635                 ent->animcache_tvector3f = NULL;
4636                 ent->animcache_vertexmesh = NULL;
4637                 ent->animcache_vertex3fbuffer = NULL;
4638                 ent->animcache_vertexmeshbuffer = NULL;
4639         }
4640 }
4641
4642 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4643 {
4644         int i;
4645
4646         // check if we need the meshbuffers
4647         if (!vid.useinterleavedarrays)
4648                 return;
4649
4650         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4651                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4652         // TODO: upload vertex3f buffer?
4653         if (ent->animcache_vertexmesh)
4654         {
4655                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4656                 for (i = 0;i < numvertices;i++)
4657                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4658                 if (ent->animcache_svector3f)
4659                         for (i = 0;i < numvertices;i++)
4660                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4661                 if (ent->animcache_tvector3f)
4662                         for (i = 0;i < numvertices;i++)
4663                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4664                 if (ent->animcache_normal3f)
4665                         for (i = 0;i < numvertices;i++)
4666                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4667                 // TODO: upload vertexmeshbuffer?
4668         }
4669 }
4670
4671 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4672 {
4673         dp_model_t *model = ent->model;
4674         int numvertices;
4675         // see if it's already cached this frame
4676         if (ent->animcache_vertex3f)
4677         {
4678                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4679                 if (wantnormals || wanttangents)
4680                 {
4681                         if (ent->animcache_normal3f)
4682                                 wantnormals = false;
4683                         if (ent->animcache_svector3f)
4684                                 wanttangents = false;
4685                         if (wantnormals || wanttangents)
4686                         {
4687                                 numvertices = model->surfmesh.num_vertices;
4688                                 if (wantnormals)
4689                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4690                                 if (wanttangents)
4691                                 {
4692                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4693                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4694                                 }
4695                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4696                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4697                         }
4698                 }
4699         }
4700         else
4701         {
4702                 // see if this ent is worth caching
4703                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4704                         return false;
4705                 // get some memory for this entity and generate mesh data
4706                 numvertices = model->surfmesh.num_vertices;
4707                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4708                 if (wantnormals)
4709                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4710                 if (wanttangents)
4711                 {
4712                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4713                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                 }
4715                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4716                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4717         }
4718         return true;
4719 }
4720
4721 void R_AnimCache_CacheVisibleEntities(void)
4722 {
4723         int i;
4724         qboolean wantnormals = true;
4725         qboolean wanttangents = !r_showsurfaces.integer;
4726
4727         switch(vid.renderpath)
4728         {
4729         case RENDERPATH_GL20:
4730         case RENDERPATH_D3D9:
4731         case RENDERPATH_D3D10:
4732         case RENDERPATH_D3D11:
4733         case RENDERPATH_GLES2:
4734                 break;
4735         case RENDERPATH_GL11:
4736         case RENDERPATH_GL13:
4737         case RENDERPATH_GLES1:
4738                 wanttangents = false;
4739                 break;
4740         case RENDERPATH_SOFT:
4741                 break;
4742         }
4743
4744         if (r_shownormals.integer)
4745                 wanttangents = wantnormals = true;
4746
4747         // TODO: thread this
4748         // NOTE: R_PrepareRTLights() also caches entities
4749
4750         for (i = 0;i < r_refdef.scene.numentities;i++)
4751                 if (r_refdef.viewcache.entityvisible[i])
4752                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4753 }
4754
4755 //==================================================================================
4756
4757 extern cvar_t r_overheadsprites_pushback;
4758
4759 static void R_View_UpdateEntityLighting (void)
4760 {
4761         int i;
4762         entity_render_t *ent;
4763         vec3_t tempdiffusenormal, avg;
4764         vec_t f, fa, fd, fdd;
4765         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4766
4767         for (i = 0;i < r_refdef.scene.numentities;i++)
4768         {
4769                 ent = r_refdef.scene.entities[i];
4770
4771                 // skip unseen models
4772                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4773                         continue;
4774
4775                 // skip bsp models
4776                 if (ent->model && ent->model->brush.num_leafs)
4777                 {
4778                         // TODO: use modellight for r_ambient settings on world?
4779                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4780                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4781                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4782                         continue;
4783                 }
4784
4785                 // fetch the lighting from the worldmodel data
4786                 VectorClear(ent->modellight_ambient);
4787                 VectorClear(ent->modellight_diffuse);
4788                 VectorClear(tempdiffusenormal);
4789                 if (ent->flags & RENDER_LIGHT)
4790                 {
4791                         vec3_t org;
4792                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4793
4794                         // complete lightning for lit sprites
4795                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4796                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4797                         {
4798                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4799                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4800                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4801                         }
4802                         else
4803                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4804
4805                         if(ent->flags & RENDER_EQUALIZE)
4806                         {
4807                                 // first fix up ambient lighting...
4808                                 if(r_equalize_entities_minambient.value > 0)
4809                                 {
4810                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4811                                         if(fd > 0)
4812                                         {
4813                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4814                                                 if(fa < r_equalize_entities_minambient.value * fd)
4815                                                 {
4816                                                         // solve:
4817                                                         //   fa'/fd' = minambient
4818                                                         //   fa'+0.25*fd' = fa+0.25*fd
4819                                                         //   ...
4820                                                         //   fa' = fd' * minambient
4821                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4822                                                         //   ...
4823                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4824                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4825                                                         //   ...
4826                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4827                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4828                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4829                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4830                                                 }
4831                                         }
4832                                 }
4833
4834                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4835                                 {
4836                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4837                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4838                                         f = fa + 0.25 * fd;
4839                                         if(f > 0)
4840                                         {
4841                                                 // adjust brightness and saturation to target
4842                                                 avg[0] = avg[1] = avg[2] = fa / f;
4843                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4844                                                 avg[0] = avg[1] = avg[2] = fd / f;
4845                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4846                                         }
4847                                 }
4848                         }
4849                 }
4850                 else // highly rare
4851                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4852
4853                 // move the light direction into modelspace coordinates for lighting code
4854                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4855                 if(VectorLength2(ent->modellight_lightdir) == 0)
4856                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4857                 VectorNormalize(ent->modellight_lightdir);
4858         }
4859 }
4860
4861 #define MAX_LINEOFSIGHTTRACES 64
4862
4863 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4864 {
4865         int i;
4866         vec3_t boxmins, boxmaxs;
4867         vec3_t start;
4868         vec3_t end;
4869         dp_model_t *model = r_refdef.scene.worldmodel;
4870
4871         if (!model || !model->brush.TraceLineOfSight)
4872                 return true;
4873
4874         // expand the box a little
4875         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4876         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4877         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4878         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4879         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4880         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4881
4882         // return true if eye is inside enlarged box
4883         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4884                 return true;
4885
4886         // try center
4887         VectorCopy(eye, start);
4888         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4889         if (model->brush.TraceLineOfSight(model, start, end))
4890                 return true;
4891
4892         // try various random positions
4893         for (i = 0;i < numsamples;i++)
4894         {
4895                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4896                 if (model->brush.TraceLineOfSight(model, start, end))
4897                         return true;
4898         }
4899
4900         return false;
4901 }
4902
4903
4904 static void R_View_UpdateEntityVisible (void)
4905 {
4906         int i;
4907         int renderimask;
4908         int samples;
4909         entity_render_t *ent;
4910
4911         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4912                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4913                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4914                 :                                                          RENDER_EXTERIORMODEL;
4915         if (!r_drawviewmodel.integer)
4916                 renderimask |= RENDER_VIEWMODEL;
4917         if (!r_drawexteriormodel.integer)
4918                 renderimask |= RENDER_EXTERIORMODEL;
4919         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4920         {
4921                 // worldmodel can check visibility
4922                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4923                 for (i = 0;i < r_refdef.scene.numentities;i++)
4924                 {
4925                         ent = r_refdef.scene.entities[i];
4926                         if (!(ent->flags & renderimask))
4927                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4928                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4929                                 r_refdef.viewcache.entityvisible[i] = true;
4930                 }
4931         }
4932         else
4933         {
4934                 // no worldmodel or it can't check visibility
4935                 for (i = 0;i < r_refdef.scene.numentities;i++)
4936                 {
4937                         ent = r_refdef.scene.entities[i];
4938                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4939                 }
4940         }
4941         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4942                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4943         {
4944                 for (i = 0;i < r_refdef.scene.numentities;i++)
4945                 {
4946                         if (!r_refdef.viewcache.entityvisible[i])
4947                                 continue;
4948                         ent = r_refdef.scene.entities[i];
4949                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4950                         {
4951                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4952                                 if (samples < 0)
4953                                         continue; // temp entities do pvs only
4954                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4955                                         ent->last_trace_visibility = realtime;
4956                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4957                                         r_refdef.viewcache.entityvisible[i] = 0;
4958                         }
4959                 }
4960         }
4961 }
4962
4963 /// only used if skyrendermasked, and normally returns false
4964 int R_DrawBrushModelsSky (void)
4965 {
4966         int i, sky;
4967         entity_render_t *ent;
4968
4969         sky = false;
4970         for (i = 0;i < r_refdef.scene.numentities;i++)
4971         {
4972                 if (!r_refdef.viewcache.entityvisible[i])
4973                         continue;
4974                 ent = r_refdef.scene.entities[i];
4975                 if (!ent->model || !ent->model->DrawSky)
4976                         continue;
4977                 ent->model->DrawSky(ent);
4978                 sky = true;
4979         }
4980         return sky;
4981 }
4982
4983 static void R_DrawNoModel(entity_render_t *ent);
4984 static void R_DrawModels(void)
4985 {
4986         int i;
4987         entity_render_t *ent;
4988
4989         for (i = 0;i < r_refdef.scene.numentities;i++)
4990         {
4991                 if (!r_refdef.viewcache.entityvisible[i])
4992                         continue;
4993                 ent = r_refdef.scene.entities[i];
4994                 r_refdef.stats.entities++;
4995                 /*
4996                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4997                 {
4998                         vec3_t f, l, u, o;
4999                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5000                         Con_Printf("R_DrawModels\n");
5001                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5002                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5003                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5004                 }
5005                 */
5006                 if (ent->model && ent->model->Draw != NULL)
5007                         ent->model->Draw(ent);
5008                 else
5009                         R_DrawNoModel(ent);
5010         }
5011 }
5012
5013 static void R_DrawModelsDepth(void)
5014 {
5015         int i;
5016         entity_render_t *ent;
5017
5018         for (i = 0;i < r_refdef.scene.numentities;i++)
5019         {
5020                 if (!r_refdef.viewcache.entityvisible[i])
5021                         continue;
5022                 ent = r_refdef.scene.entities[i];
5023                 if (ent->model && ent->model->DrawDepth != NULL)
5024                         ent->model->DrawDepth(ent);
5025         }
5026 }
5027
5028 static void R_DrawModelsDebug(void)
5029 {
5030         int i;
5031         entity_render_t *ent;
5032
5033         for (i = 0;i < r_refdef.scene.numentities;i++)
5034         {
5035                 if (!r_refdef.viewcache.entityvisible[i])
5036                         continue;
5037                 ent = r_refdef.scene.entities[i];
5038                 if (ent->model && ent->model->DrawDebug != NULL)
5039                         ent->model->DrawDebug(ent);
5040         }
5041 }
5042
5043 static void R_DrawModelsAddWaterPlanes(void)
5044 {
5045         int i;
5046         entity_render_t *ent;
5047
5048         for (i = 0;i < r_refdef.scene.numentities;i++)
5049         {
5050                 if (!r_refdef.viewcache.entityvisible[i])
5051                         continue;
5052                 ent = r_refdef.scene.entities[i];
5053                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5054                         ent->model->DrawAddWaterPlanes(ent);
5055         }
5056 }
5057
5058 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5059 {
5060         if (r_hdr_irisadaptation.integer)
5061         {
5062                 vec3_t ambient;
5063                 vec3_t diffuse;
5064                 vec3_t diffusenormal;
5065                 vec_t brightness;
5066                 vec_t goal;
5067                 vec_t current;
5068                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5069                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5070                 brightness = max(0.0000001f, brightness);
5071                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5072                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5073                 current = r_hdr_irisadaptation_value.value;
5074                 if (current < goal)
5075                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5076                 else if (current > goal)
5077                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5078                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5079                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5080         }
5081         else if (r_hdr_irisadaptation_value.value != 1.0f)
5082                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5083 }
5084
5085 static void R_View_SetFrustum(const int *scissor)
5086 {
5087         int i;
5088         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5089         vec3_t forward, left, up, origin, v;
5090
5091         if(scissor)
5092         {
5093                 // flipped x coordinates (because x points left here)
5094                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5095                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096
5097                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5098                 switch(vid.renderpath)
5099                 {
5100                         case RENDERPATH_D3D9:
5101                         case RENDERPATH_D3D10:
5102                         case RENDERPATH_D3D11:
5103                                 // non-flipped y coordinates
5104                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5105                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 break;
5107                         case RENDERPATH_SOFT:
5108                         case RENDERPATH_GL11:
5109                         case RENDERPATH_GL13:
5110                         case RENDERPATH_GL20:
5111                         case RENDERPATH_GLES1:
5112                         case RENDERPATH_GLES2:
5113                                 // non-flipped y coordinates
5114                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5115                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 break;
5117                 }
5118         }
5119
5120         // we can't trust r_refdef.view.forward and friends in reflected scenes
5121         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5122
5123 #if 0
5124         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5125         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5126         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5127         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5128         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5129         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5130         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5131         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5132         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5133         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5134         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5135         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5136 #endif
5137
5138 #if 0
5139         zNear = r_refdef.nearclip;
5140         nudge = 1.0 - 1.0 / (1<<23);
5141         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5142         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5144         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5145         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5146         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5148         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5149 #endif
5150
5151
5152
5153 #if 0
5154         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5155         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5156         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5157         r_refdef.view.frustum[0].dist = m[15] - m[12];
5158
5159         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5160         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5161         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5162         r_refdef.view.frustum[1].dist = m[15] + m[12];
5163
5164         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5165         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5166         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5167         r_refdef.view.frustum[2].dist = m[15] - m[13];
5168
5169         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5170         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5171         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5172         r_refdef.view.frustum[3].dist = m[15] + m[13];
5173
5174         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5175         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5176         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5177         r_refdef.view.frustum[4].dist = m[15] - m[14];
5178
5179         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5180         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5181         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5182         r_refdef.view.frustum[5].dist = m[15] + m[14];
5183 #endif
5184
5185         if (r_refdef.view.useperspective)
5186         {
5187                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5188                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5189                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5190                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5191                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5192
5193                 // then the normals from the corners relative to origin
5194                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5195                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5198
5199                 // in a NORMAL view, forward cross left == up
5200                 // in a REFLECTED view, forward cross left == down
5201                 // so our cross products above need to be adjusted for a left handed coordinate system
5202                 CrossProduct(forward, left, v);
5203                 if(DotProduct(v, up) < 0)
5204                 {
5205                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5206                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5207                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5208                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5209                 }
5210
5211                 // Leaving those out was a mistake, those were in the old code, and they
5212                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5213                 // I couldn't reproduce it after adding those normalizations. --blub
5214                 VectorNormalize(r_refdef.view.frustum[0].normal);
5215                 VectorNormalize(r_refdef.view.frustum[1].normal);
5216                 VectorNormalize(r_refdef.view.frustum[2].normal);
5217                 VectorNormalize(r_refdef.view.frustum[3].normal);
5218
5219                 // make the corners absolute
5220                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5221                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5222                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5223                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5224
5225                 // one more normal
5226                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5227
5228                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5229                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5230                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5231                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5232                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5233         }
5234         else
5235         {
5236                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5237                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5238                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5239                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5240                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5241                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5242                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5244                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5246         }
5247         r_refdef.view.numfrustumplanes = 5;
5248
5249         if (r_refdef.view.useclipplane)
5250         {
5251                 r_refdef.view.numfrustumplanes = 6;
5252                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5253         }
5254
5255         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5256                 PlaneClassify(r_refdef.view.frustum + i);
5257
5258         // LordHavoc: note to all quake engine coders, Quake had a special case
5259         // for 90 degrees which assumed a square view (wrong), so I removed it,
5260         // Quake2 has it disabled as well.
5261
5262         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5263         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5264         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5265         //PlaneClassify(&frustum[0]);
5266
5267         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5268         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5269         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5270         //PlaneClassify(&frustum[1]);
5271
5272         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5273         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5274         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5275         //PlaneClassify(&frustum[2]);
5276
5277         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5278         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5279         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5280         //PlaneClassify(&frustum[3]);
5281
5282         // nearclip plane
5283         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5284         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5285         //PlaneClassify(&frustum[4]);
5286 }
5287
5288 void R_View_UpdateWithScissor(const int *myscissor)
5289 {
5290         R_Main_ResizeViewCache();
5291         R_View_SetFrustum(myscissor);
5292         R_View_WorldVisibility(r_refdef.view.useclipplane);
5293         R_View_UpdateEntityVisible();
5294         R_View_UpdateEntityLighting();
5295 }
5296
5297 void R_View_Update(void)
5298 {
5299         R_Main_ResizeViewCache();
5300         R_View_SetFrustum(NULL);
5301         R_View_WorldVisibility(r_refdef.view.useclipplane);
5302         R_View_UpdateEntityVisible();
5303         R_View_UpdateEntityLighting();
5304 }
5305
5306 float viewscalefpsadjusted = 1.0f;
5307
5308 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5309 {
5310         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5311         scale = bound(0.03125f, scale, 1.0f);
5312         *outwidth = (int)ceil(width * scale);
5313         *outheight = (int)ceil(height * scale);
5314 }
5315
5316 void R_Mesh_SetMainRenderTargets(void)
5317 {
5318         if (r_bloomstate.fbo_framebuffer)
5319                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5320         else
5321                 R_Mesh_ResetRenderTargets();
5322 }
5323
5324 void R_SetupView(qboolean allowwaterclippingplane)
5325 {
5326         const float *customclipplane = NULL;
5327         float plane[4];
5328         int scaledwidth, scaledheight;
5329         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5330         {
5331                 // LordHavoc: couldn't figure out how to make this approach the
5332                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5333                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5334                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5335                         dist = r_refdef.view.clipplane.dist;
5336                 plane[0] = r_refdef.view.clipplane.normal[0];
5337                 plane[1] = r_refdef.view.clipplane.normal[1];
5338                 plane[2] = r_refdef.view.clipplane.normal[2];
5339                 plane[3] = -dist;
5340                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5341         }
5342
5343         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5344         if (!r_refdef.view.useperspective)
5345                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5346         else if (vid.stencil && r_useinfinitefarclip.integer)
5347                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5348         else
5349                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5350         R_Mesh_SetMainRenderTargets();
5351         R_SetViewport(&r_refdef.view.viewport);
5352         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5353         {
5354                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5355                 float screenplane[4];
5356                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5357                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5358                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5359                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5360                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5361         }
5362 }
5363
5364 void R_EntityMatrix(const matrix4x4_t *matrix)
5365 {
5366         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5367         {
5368                 gl_modelmatrixchanged = false;
5369                 gl_modelmatrix = *matrix;
5370                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5371                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5372                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5373                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5374                 CHECKGLERROR
5375                 switch(vid.renderpath)
5376                 {
5377                 case RENDERPATH_D3D9:
5378 #ifdef SUPPORTD3D
5379                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5380                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5381 #endif
5382                         break;
5383                 case RENDERPATH_D3D10:
5384                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5385                         break;
5386                 case RENDERPATH_D3D11:
5387                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5388                         break;
5389                 case RENDERPATH_GL11:
5390                 case RENDERPATH_GL13:
5391                 case RENDERPATH_GLES1:
5392                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5393                         break;
5394                 case RENDERPATH_SOFT:
5395                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5396                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5397                         break;
5398                 case RENDERPATH_GL20:
5399                 case RENDERPATH_GLES2:
5400                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5401                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5402                         break;
5403                 }
5404         }
5405 }
5406
5407 void R_ResetViewRendering2D(void)
5408 {
5409         r_viewport_t viewport;
5410         DrawQ_Finish();
5411
5412         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5413         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5414         R_Mesh_ResetRenderTargets();
5415         R_SetViewport(&viewport);
5416         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5417         GL_Color(1, 1, 1, 1);
5418         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5419         GL_BlendFunc(GL_ONE, GL_ZERO);
5420         GL_ScissorTest(false);
5421         GL_DepthMask(false);
5422         GL_DepthRange(0, 1);
5423         GL_DepthTest(false);
5424         GL_DepthFunc(GL_LEQUAL);
5425         R_EntityMatrix(&identitymatrix);
5426         R_Mesh_ResetTextureState();
5427         GL_PolygonOffset(0, 0);
5428         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5429         switch(vid.renderpath)
5430         {
5431         case RENDERPATH_GL11:
5432         case RENDERPATH_GL13:
5433         case RENDERPATH_GL20:
5434         case RENDERPATH_GLES1:
5435         case RENDERPATH_GLES2:
5436                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5437                 break;
5438         case RENDERPATH_D3D9:
5439         case RENDERPATH_D3D10:
5440         case RENDERPATH_D3D11:
5441         case RENDERPATH_SOFT:
5442                 break;
5443         }
5444         GL_CullFace(GL_NONE);
5445 }
5446
5447 void R_ResetViewRendering3D(void)
5448 {
5449         DrawQ_Finish();
5450
5451         R_SetupView(true);
5452         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5453         GL_Color(1, 1, 1, 1);
5454         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5455         GL_BlendFunc(GL_ONE, GL_ZERO);
5456         GL_ScissorTest(true);
5457         GL_DepthMask(true);
5458         GL_DepthRange(0, 1);
5459         GL_DepthTest(true);
5460         GL_DepthFunc(GL_LEQUAL);
5461         R_EntityMatrix(&identitymatrix);
5462         R_Mesh_ResetTextureState();
5463         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5464         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5465         switch(vid.renderpath)
5466         {
5467         case RENDERPATH_GL11:
5468         case RENDERPATH_GL13:
5469         case RENDERPATH_GL20:
5470         case RENDERPATH_GLES1:
5471         case RENDERPATH_GLES2:
5472                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5473                 break;
5474         case RENDERPATH_D3D9:
5475         case RENDERPATH_D3D10:
5476         case RENDERPATH_D3D11:
5477         case RENDERPATH_SOFT:
5478                 break;
5479         }
5480         GL_CullFace(r_refdef.view.cullface_back);
5481 }
5482
5483 /*
5484 ================
5485 R_RenderView_UpdateViewVectors
5486 ================
5487 */
5488 static void R_RenderView_UpdateViewVectors(void)
5489 {
5490         // break apart the view matrix into vectors for various purposes
5491         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5492         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5493         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5494         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5495         // make an inverted copy of the view matrix for tracking sprites
5496         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5497 }
5498
5499 void R_RenderScene(void);
5500 void R_RenderWaterPlanes(void);
5501
5502 static void R_Water_StartFrame(void)
5503 {
5504         int i;
5505         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5506         r_waterstate_waterplane_t *p;
5507
5508         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5509                 return;
5510
5511         switch(vid.renderpath)
5512         {
5513         case RENDERPATH_GL20:
5514         case RENDERPATH_D3D9:
5515         case RENDERPATH_D3D10:
5516         case RENDERPATH_D3D11:
5517         case RENDERPATH_SOFT:
5518         case RENDERPATH_GLES2:
5519                 break;
5520         case RENDERPATH_GL11:
5521         case RENDERPATH_GL13:
5522         case RENDERPATH_GLES1:
5523                 return;
5524         }
5525
5526         // set waterwidth and waterheight to the water resolution that will be
5527         // used (often less than the screen resolution for faster rendering)
5528         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5529
5530         // calculate desired texture sizes
5531         // can't use water if the card does not support the texture size
5532         if (!r_water.integer || r_showsurfaces.integer)
5533                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5534         else if (vid.support.arb_texture_non_power_of_two)
5535         {
5536                 texturewidth = waterwidth;
5537                 textureheight = waterheight;
5538                 camerawidth = waterwidth;
5539                 cameraheight = waterheight;
5540         }
5541         else
5542         {
5543                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5544                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5545                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5546                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5547         }
5548
5549         // allocate textures as needed
5550         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5551         {
5552                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5553                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5554                 {
5555                         if (p->texture_refraction)
5556                                 R_FreeTexture(p->texture_refraction);
5557                         p->texture_refraction = NULL;
5558                         if (p->texture_reflection)
5559                                 R_FreeTexture(p->texture_reflection);
5560                         p->texture_reflection = NULL;
5561                         if (p->texture_camera)
5562                                 R_FreeTexture(p->texture_camera);
5563                         p->texture_camera = NULL;
5564                 }
5565                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5566                 r_waterstate.texturewidth = texturewidth;
5567                 r_waterstate.textureheight = textureheight;
5568                 r_waterstate.camerawidth = camerawidth;
5569                 r_waterstate.cameraheight = cameraheight;
5570         }
5571
5572         if (r_waterstate.texturewidth)
5573         {
5574                 int scaledwidth, scaledheight;
5575
5576                 r_waterstate.enabled = true;
5577
5578                 // when doing a reduced render (HDR) we want to use a smaller area
5579                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5580                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5581                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5582
5583                 // set up variables that will be used in shader setup
5584                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5585                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5586                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5587                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5588         }
5589
5590         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5591         r_waterstate.numwaterplanes = 0;
5592 }
5593
5594 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5595 {
5596         int triangleindex, planeindex;
5597         const int *e;
5598         vec3_t vert[3];
5599         vec3_t normal;
5600         vec3_t center;
5601         mplane_t plane;
5602         r_waterstate_waterplane_t *p;
5603         texture_t *t = R_GetCurrentTexture(surface->texture);
5604
5605         // just use the first triangle with a valid normal for any decisions
5606         VectorClear(normal);
5607         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5608         {
5609                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5610                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5611                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5612                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5613                 if (VectorLength2(normal) >= 0.001)
5614                         break;
5615         }
5616
5617         VectorCopy(normal, plane.normal);
5618         VectorNormalize(plane.normal);
5619         plane.dist = DotProduct(vert[0], plane.normal);
5620         PlaneClassify(&plane);
5621         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5622         {
5623                 // skip backfaces (except if nocullface is set)
5624                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5625                         return;
5626                 VectorNegate(plane.normal, plane.normal);
5627                 plane.dist *= -1;
5628                 PlaneClassify(&plane);
5629         }
5630
5631
5632         // find a matching plane if there is one
5633         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5634                 if(p->camera_entity == t->camera_entity)
5635                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5636                                 break;
5637         if (planeindex >= r_waterstate.maxwaterplanes)
5638                 return; // nothing we can do, out of planes
5639
5640         // if this triangle does not fit any known plane rendered this frame, add one
5641         if (planeindex >= r_waterstate.numwaterplanes)
5642         {
5643                 // store the new plane
5644                 r_waterstate.numwaterplanes++;
5645                 p->plane = plane;
5646                 // clear materialflags and pvs
5647                 p->materialflags = 0;
5648                 p->pvsvalid = false;
5649                 p->camera_entity = t->camera_entity;
5650                 VectorCopy(surface->mins, p->mins);
5651                 VectorCopy(surface->maxs, p->maxs);
5652         }
5653         else
5654         {
5655                 // merge mins/maxs
5656                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5657                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5658                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5659                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5660                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5661                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5662         }
5663         // merge this surface's materialflags into the waterplane
5664         p->materialflags |= t->currentmaterialflags;
5665         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5666         {
5667                 // merge this surface's PVS into the waterplane
5668                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5669                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5670                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5671                 {
5672                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5673                         p->pvsvalid = true;
5674                 }
5675         }
5676 }
5677
5678 extern cvar_t r_drawparticles;
5679 extern cvar_t r_drawdecals;
5680
5681 static void R_Water_ProcessPlanes(void)
5682 {
5683         int myscissor[4];
5684         r_refdef_view_t originalview;
5685         r_refdef_view_t myview;
5686         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5687         r_waterstate_waterplane_t *p;
5688         vec3_t visorigin;
5689
5690         originalview = r_refdef.view;
5691
5692         // lowquality hack, temporarily shut down some cvars and restore afterwards
5693         qualityreduction = r_water_lowquality.integer;
5694         if (qualityreduction > 0)
5695         {
5696                 if (qualityreduction >= 1)
5697                 {
5698                         old_r_shadows = r_shadows.integer;
5699                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5700                         old_r_dlight = r_shadow_realtime_dlight.integer;
5701                         Cvar_SetValueQuick(&r_shadows, 0);
5702                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5703                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5704                 }
5705                 if (qualityreduction >= 2)
5706                 {
5707                         old_r_dynamic = r_dynamic.integer;
5708                         old_r_particles = r_drawparticles.integer;
5709                         old_r_decals = r_drawdecals.integer;
5710                         Cvar_SetValueQuick(&r_dynamic, 0);
5711                         Cvar_SetValueQuick(&r_drawparticles, 0);
5712                         Cvar_SetValueQuick(&r_drawdecals, 0);
5713                 }
5714         }
5715
5716         // make sure enough textures are allocated
5717         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5718         {
5719                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5720                 {
5721                         if (!p->texture_refraction)
5722                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5723                         if (!p->texture_refraction)
5724                                 goto error;
5725                 }
5726                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5727                 {
5728                         if (!p->texture_camera)
5729                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5730                         if (!p->texture_camera)
5731                                 goto error;
5732                 }
5733
5734                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5735                 {
5736                         if (!p->texture_reflection)
5737                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5738                         if (!p->texture_reflection)
5739                                 goto error;
5740                 }
5741         }
5742
5743         // render views
5744         r_refdef.view = originalview;
5745         r_refdef.view.showdebug = false;
5746         r_refdef.view.width = r_waterstate.waterwidth;
5747         r_refdef.view.height = r_waterstate.waterheight;
5748         r_refdef.view.useclipplane = true;
5749         myview = r_refdef.view;
5750         r_waterstate.renderingscene = true;
5751         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5752         {
5753                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5754                 {
5755                         r_refdef.view = myview;
5756                         if(r_water_scissormode.integer)
5757                         {
5758                                 R_SetupView(true);
5759                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5760                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5761                         }
5762
5763                         // render reflected scene and copy into texture
5764                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5765                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5766                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5767                         r_refdef.view.clipplane = p->plane;
5768                         // reverse the cullface settings for this render
5769                         r_refdef.view.cullface_front = GL_FRONT;
5770                         r_refdef.view.cullface_back = GL_BACK;
5771                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5772                         {
5773                                 r_refdef.view.usecustompvs = true;
5774                                 if (p->pvsvalid)
5775                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5776                                 else
5777                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5778                         }
5779
5780                         R_ResetViewRendering3D();
5781                         R_ClearScreen(r_refdef.fogenabled);
5782                         if(r_water_scissormode.integer & 2)
5783                                 R_View_UpdateWithScissor(myscissor);
5784                         else
5785                                 R_View_Update();
5786                         if(r_water_scissormode.integer & 1)
5787                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5788                         R_RenderScene();
5789
5790                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5791                 }
5792
5793                 // render the normal view scene and copy into texture
5794                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5795                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5796                 {
5797                         r_refdef.view = myview;
5798                         if(r_water_scissormode.integer)
5799                         {
5800                                 R_SetupView(true);
5801                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5802                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5803                         }
5804
5805                         r_waterstate.renderingrefraction = true;
5806
5807                         r_refdef.view.clipplane = p->plane;
5808                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5809                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5810
5811                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5812                         {
5813                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5814                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5815                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5816                                 R_RenderView_UpdateViewVectors();
5817                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5818                                 {
5819                                         r_refdef.view.usecustompvs = true;
5820                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5821                                 }
5822                         }
5823
5824                         PlaneClassify(&r_refdef.view.clipplane);
5825
5826                         R_ResetViewRendering3D();
5827                         R_ClearScreen(r_refdef.fogenabled);
5828                         if(r_water_scissormode.integer & 2)
5829                                 R_View_UpdateWithScissor(myscissor);
5830                         else
5831                                 R_View_Update();
5832                         if(r_water_scissormode.integer & 1)
5833                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5834                         R_RenderScene();
5835
5836                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5837                         r_waterstate.renderingrefraction = false;
5838                 }
5839                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5840                 {
5841                         r_refdef.view = myview;
5842
5843                         r_refdef.view.clipplane = p->plane;
5844                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5845                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5846
5847                         r_refdef.view.width = r_waterstate.camerawidth;
5848                         r_refdef.view.height = r_waterstate.cameraheight;
5849                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5850                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5851
5852                         if(p->camera_entity)
5853                         {
5854                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5855                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5856                         }
5857
5858                         // note: all of the view is used for displaying... so
5859                         // there is no use in scissoring
5860
5861                         // reverse the cullface settings for this render
5862                         r_refdef.view.cullface_front = GL_FRONT;
5863                         r_refdef.view.cullface_back = GL_BACK;
5864                         // also reverse the view matrix
5865                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5866                         R_RenderView_UpdateViewVectors();
5867                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5868                         {
5869                                 r_refdef.view.usecustompvs = true;
5870                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5871                         }
5872                         
5873                         // camera needs no clipplane
5874                         r_refdef.view.useclipplane = false;
5875
5876                         PlaneClassify(&r_refdef.view.clipplane);
5877
5878                         R_ResetViewRendering3D();
5879                         R_ClearScreen(r_refdef.fogenabled);
5880                         R_View_Update();
5881                         R_RenderScene();
5882
5883                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5884                         r_waterstate.renderingrefraction = false;
5885                 }
5886
5887         }
5888         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5889         r_waterstate.renderingscene = false;
5890         r_refdef.view = originalview;
5891         R_ResetViewRendering3D();
5892         R_ClearScreen(r_refdef.fogenabled);
5893         R_View_Update();
5894         goto finish;
5895 error:
5896         r_refdef.view = originalview;
5897         r_waterstate.renderingscene = false;
5898         Cvar_SetValueQuick(&r_water, 0);
5899         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5900 finish:
5901         // lowquality hack, restore cvars
5902         if (qualityreduction > 0)
5903         {
5904                 if (qualityreduction >= 1)
5905                 {
5906                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5907                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5908                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5909                 }
5910                 if (qualityreduction >= 2)
5911                 {
5912                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5913                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5914                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5915                 }
5916         }
5917 }
5918
5919 void R_Bloom_StartFrame(void)
5920 {
5921         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5922         int viewwidth, viewheight;
5923         textype_t textype;
5924
5925         if (r_viewscale_fpsscaling.integer)
5926         {
5927                 double actualframetime;
5928                 double targetframetime;
5929                 double adjust;
5930                 actualframetime = r_refdef.lastdrawscreentime;
5931                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5932                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5933                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5934                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5935                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5936                 viewscalefpsadjusted += adjust;
5937                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5938         }
5939         else
5940                 viewscalefpsadjusted = 1.0f;
5941
5942         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5943
5944         switch(vid.renderpath)
5945         {
5946         case RENDERPATH_GL20:
5947         case RENDERPATH_D3D9:
5948         case RENDERPATH_D3D10:
5949         case RENDERPATH_D3D11:
5950         case RENDERPATH_SOFT:
5951         case RENDERPATH_GLES2:
5952                 break;
5953         case RENDERPATH_GL11:
5954         case RENDERPATH_GL13:
5955         case RENDERPATH_GLES1:
5956                 return;
5957         }
5958
5959         // set bloomwidth and bloomheight to the bloom resolution that will be
5960         // used (often less than the screen resolution for faster rendering)
5961         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5962         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5963         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5964         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5965         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5966
5967         // calculate desired texture sizes
5968         if (vid.support.arb_texture_non_power_of_two)
5969         {
5970                 screentexturewidth = vid.width;
5971                 screentextureheight = vid.height;
5972                 bloomtexturewidth = r_bloomstate.bloomwidth;
5973                 bloomtextureheight = r_bloomstate.bloomheight;
5974         }
5975         else
5976         {
5977                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5978                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5979                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5980                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5981         }
5982
5983         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5984         {
5985                 Cvar_SetValueQuick(&r_hdr, 0);
5986                 Cvar_SetValueQuick(&r_bloom, 0);
5987                 Cvar_SetValueQuick(&r_motionblur, 0);
5988                 Cvar_SetValueQuick(&r_damageblur, 0);
5989         }
5990
5991         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5992                 screentexturewidth = screentextureheight = 0;
5993         if (!r_hdr.integer && !r_bloom.integer)
5994                 bloomtexturewidth = bloomtextureheight = 0;
5995
5996         textype = TEXTYPE_COLORBUFFER;
5997         switch (vid.renderpath)
5998         {
5999         case RENDERPATH_GL20:
6000         case RENDERPATH_GLES2:
6001                 if (vid.support.ext_framebuffer_object)
6002                 {
6003                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6004                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6005                 }
6006                 break;
6007         case RENDERPATH_GL11:
6008         case RENDERPATH_GL13:
6009         case RENDERPATH_GLES1:
6010         case RENDERPATH_D3D9:
6011         case RENDERPATH_D3D10:
6012         case RENDERPATH_D3D11:
6013         case RENDERPATH_SOFT:
6014                 break;
6015         }
6016
6017         // allocate textures as needed
6018         if (r_bloomstate.screentexturewidth != screentexturewidth
6019          || r_bloomstate.screentextureheight != screentextureheight
6020          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6021          || r_bloomstate.bloomtextureheight != bloomtextureheight
6022          || r_bloomstate.texturetype != textype
6023          || r_bloomstate.viewfbo != r_viewfbo.integer)
6024         {
6025                 if (r_bloomstate.texture_bloom)
6026                         R_FreeTexture(r_bloomstate.texture_bloom);
6027                 r_bloomstate.texture_bloom = NULL;
6028                 if (r_bloomstate.texture_screen)
6029                         R_FreeTexture(r_bloomstate.texture_screen);
6030                 r_bloomstate.texture_screen = NULL;
6031                 if (r_bloomstate.fbo_framebuffer)
6032                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6033                 r_bloomstate.fbo_framebuffer = 0;
6034                 if (r_bloomstate.texture_framebuffercolor)
6035                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6036                 r_bloomstate.texture_framebuffercolor = NULL;
6037                 if (r_bloomstate.texture_framebufferdepth)
6038                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6039                 r_bloomstate.texture_framebufferdepth = NULL;
6040                 r_bloomstate.screentexturewidth = screentexturewidth;
6041                 r_bloomstate.screentextureheight = screentextureheight;
6042                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6043                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6044                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6045                 {
6046                         // FIXME: choose depth bits based on a cvar
6047                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6048                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6049                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6050                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6051 #ifndef USE_GLES2
6052                         // render depth into one texture and normalmap into the other
6053                         if (qglDrawBuffer)
6054                         {
6055                                 int status;
6056                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6057                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6058                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6059                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6060                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6061                         }
6062 #endif
6063                 }
6064                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6065                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6066                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6067                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6068                 r_bloomstate.viewfbo = r_viewfbo.integer;
6069                 r_bloomstate.texturetype = textype;
6070         }
6071
6072         // when doing a reduced render (HDR) we want to use a smaller area
6073         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6074         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6075         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6076         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6077         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6078
6079         // set up a texcoord array for the full resolution screen image
6080         // (we have to keep this around to copy back during final render)
6081         r_bloomstate.screentexcoord2f[0] = 0;
6082         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6083         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6084         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6085         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6086         r_bloomstate.screentexcoord2f[5] = 0;
6087         r_bloomstate.screentexcoord2f[6] = 0;
6088         r_bloomstate.screentexcoord2f[7] = 0;
6089
6090         // set up a texcoord array for the reduced resolution bloom image
6091         // (which will be additive blended over the screen image)
6092         r_bloomstate.bloomtexcoord2f[0] = 0;
6093         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6094         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6095         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6096         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6097         r_bloomstate.bloomtexcoord2f[5] = 0;
6098         r_bloomstate.bloomtexcoord2f[6] = 0;
6099         r_bloomstate.bloomtexcoord2f[7] = 0;
6100
6101         switch(vid.renderpath)
6102         {
6103         case RENDERPATH_GL11:
6104         case RENDERPATH_GL13:
6105         case RENDERPATH_GL20:
6106         case RENDERPATH_SOFT:
6107         case RENDERPATH_GLES1:
6108         case RENDERPATH_GLES2:
6109                 break;
6110         case RENDERPATH_D3D9:
6111         case RENDERPATH_D3D10:
6112         case RENDERPATH_D3D11:
6113                 {
6114                         int i;
6115                         for (i = 0;i < 4;i++)
6116                         {
6117                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6118                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6119                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6120                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6121                         }
6122                 }
6123                 break;
6124         }
6125
6126         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6127         {
6128                 r_bloomstate.enabled = true;
6129                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6130         }
6131
6132         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6133
6134         if (r_bloomstate.fbo_framebuffer)
6135                 r_refdef.view.clear = true;
6136 }
6137
6138 void R_Bloom_CopyBloomTexture(float colorscale)
6139 {
6140         r_refdef.stats.bloom++;
6141
6142         // scale down screen texture to the bloom texture size
6143         CHECKGLERROR
6144         R_Mesh_SetMainRenderTargets();
6145         R_SetViewport(&r_bloomstate.viewport);
6146         GL_BlendFunc(GL_ONE, GL_ZERO);
6147         GL_Color(colorscale, colorscale, colorscale, 1);
6148         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6149         switch(vid.renderpath)
6150         {
6151         case RENDERPATH_GL11:
6152         case RENDERPATH_GL13:
6153         case RENDERPATH_GL20:
6154         case RENDERPATH_GLES1:
6155         case RENDERPATH_GLES2:
6156         case RENDERPATH_SOFT:
6157                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6158                 break;
6159         case RENDERPATH_D3D9:
6160         case RENDERPATH_D3D10:
6161         case RENDERPATH_D3D11:
6162                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6163                 break;
6164         }
6165         // TODO: do boxfilter scale-down in shader?
6166         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6167         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6168         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6169
6170         // we now have a bloom image in the framebuffer
6171         // copy it into the bloom image texture for later processing
6172         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6173         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6174 }
6175
6176 void R_Bloom_CopyHDRTexture(void)
6177 {
6178         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6179         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6180 }
6181
6182 void R_Bloom_MakeTexture(void)
6183 {
6184         int x, range, dir;
6185         float xoffset, yoffset, r, brighten;
6186
6187         r_refdef.stats.bloom++;
6188
6189         R_ResetViewRendering2D();
6190
6191         // we have a bloom image in the framebuffer
6192         CHECKGLERROR
6193         R_SetViewport(&r_bloomstate.viewport);
6194
6195         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6196         {
6197                 x *= 2;
6198                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6199                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6200                 GL_Color(r,r,r,1);
6201                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6202                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6203                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6204                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6205
6206                 // copy the vertically blurred bloom view to a texture
6207                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6208                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6209         }
6210
6211         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6212         brighten = r_bloom_brighten.value;
6213         if (r_bloomstate.hdr)
6214                 brighten *= r_hdr_range.value;
6215         brighten = sqrt(brighten);
6216         if(range >= 1)
6217                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6218         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6219
6220         for (dir = 0;dir < 2;dir++)
6221         {
6222                 // blend on at multiple vertical offsets to achieve a vertical blur
6223                 // TODO: do offset blends using GLSL
6224                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6225                 GL_BlendFunc(GL_ONE, GL_ZERO);
6226                 for (x = -range;x <= range;x++)
6227                 {
6228                         if (!dir){xoffset = 0;yoffset = x;}
6229                         else {xoffset = x;yoffset = 0;}
6230                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6231                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6232                         // compute a texcoord array with the specified x and y offset
6233                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6234                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6235                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6236                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6237                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6238                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6239                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6240                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6241                         // this r value looks like a 'dot' particle, fading sharply to
6242                         // black at the edges
6243                         // (probably not realistic but looks good enough)
6244                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6245                         //r = brighten/(range*2+1);
6246                         r = brighten / (range * 2 + 1);
6247                         if(range >= 1)
6248                                 r *= (1 - x*x/(float)(range*range));
6249                         GL_Color(r, r, r, 1);
6250                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6251                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6253                         GL_BlendFunc(GL_ONE, GL_ONE);
6254                 }
6255
6256                 // copy the vertically blurred bloom view to a texture
6257                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6258                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6259         }
6260 }
6261
6262 void R_HDR_RenderBloomTexture(void)
6263 {
6264         int oldwidth, oldheight;
6265         float oldcolorscale;
6266         qboolean oldwaterstate;
6267
6268         oldwaterstate = r_waterstate.enabled;
6269         oldcolorscale = r_refdef.view.colorscale;
6270         oldwidth = r_refdef.view.width;
6271         oldheight = r_refdef.view.height;
6272         r_refdef.view.width = r_bloomstate.bloomwidth;
6273         r_refdef.view.height = r_bloomstate.bloomheight;
6274
6275         if(r_hdr.integer < 2)
6276                 r_waterstate.enabled = false;
6277
6278         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6279         // TODO: add exposure compensation features
6280         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6281
6282         r_refdef.view.showdebug = false;
6283         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6284
6285         R_ResetViewRendering3D();
6286
6287         R_ClearScreen(r_refdef.fogenabled);
6288         if (r_timereport_active)
6289                 R_TimeReport("HDRclear");
6290
6291         R_View_Update();
6292         if (r_timereport_active)
6293                 R_TimeReport("visibility");
6294
6295         // only do secondary renders with HDR if r_hdr is 2 or higher
6296         r_waterstate.numwaterplanes = 0;
6297         if (r_waterstate.enabled)
6298                 R_RenderWaterPlanes();
6299
6300         r_refdef.view.showdebug = true;
6301         R_RenderScene();
6302         r_waterstate.numwaterplanes = 0;
6303
6304         R_ResetViewRendering2D();
6305
6306         R_Bloom_CopyHDRTexture();
6307         R_Bloom_MakeTexture();
6308
6309         // restore the view settings
6310         r_waterstate.enabled = oldwaterstate;
6311         r_refdef.view.width = oldwidth;
6312         r_refdef.view.height = oldheight;
6313         r_refdef.view.colorscale = oldcolorscale;
6314
6315         R_ResetViewRendering3D();
6316
6317         R_ClearScreen(r_refdef.fogenabled);
6318         if (r_timereport_active)
6319                 R_TimeReport("viewclear");
6320 }
6321
6322 static void R_BlendView(void)
6323 {
6324         unsigned int permutation;
6325         float uservecs[4][4];
6326
6327         switch (vid.renderpath)
6328         {
6329         case RENDERPATH_GL20:
6330         case RENDERPATH_D3D9:
6331         case RENDERPATH_D3D10:
6332         case RENDERPATH_D3D11:
6333         case RENDERPATH_SOFT:
6334         case RENDERPATH_GLES2:
6335                 permutation =
6336                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6337                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6338                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6339                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6340                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6341
6342                 if (r_bloomstate.texture_screen)
6343                 {
6344                         // make sure the buffer is available
6345                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6346
6347                         R_ResetViewRendering2D();
6348                         R_Mesh_SetMainRenderTargets();
6349
6350                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6351                         {
6352                                 // declare variables
6353                                 float blur_factor, blur_mouseaccel, blur_velocity;
6354                                 static float blur_average; 
6355                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6356
6357                                 // set a goal for the factoring
6358                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6359                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6360                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6361                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6362                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6363                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6364
6365                                 // from the goal, pick an averaged value between goal and last value
6366                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6367                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6368                                 
6369                                 // enforce minimum amount of blur 
6370                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6371                                 
6372                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6373
6374                                 // calculate values into a standard alpha
6375                                 cl.motionbluralpha = 1 - exp(-
6376                                                 (
6377                                                  (r_motionblur.value * blur_factor / 80)
6378                                                  +
6379                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6380                                                 )
6381                                                 /
6382                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6383                                           );
6384                                 
6385                                 // randomization for the blur value to combat persistent ghosting
6386                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6387                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6388                                 
6389                                 // apply the blur
6390                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6391                                 {
6392                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6393                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6394                                         switch(vid.renderpath)
6395                                         {
6396                                         case RENDERPATH_GL11:
6397                                         case RENDERPATH_GL13:
6398                                         case RENDERPATH_GL20:
6399                                         case RENDERPATH_GLES1:
6400                                         case RENDERPATH_GLES2:
6401                                         case RENDERPATH_SOFT:
6402                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6403                                                 break;
6404                                         case RENDERPATH_D3D9:
6405                                         case RENDERPATH_D3D10:
6406                                         case RENDERPATH_D3D11:
6407                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6408                                                 break;
6409                                         }
6410                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6411                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6412                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6413                                 }
6414                                 
6415                                 // updates old view angles for next pass 
6416                                 VectorCopy(cl.viewangles, blur_oldangles);
6417                         }
6418
6419                         // copy view into the screen texture
6420                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6421                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6422                 }
6423                 else if (!r_bloomstate.texture_bloom)
6424                 {
6425                         // we may still have to do view tint...
6426                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6427                         {
6428                                 // apply a color tint to the whole view
6429                                 R_ResetViewRendering2D();
6430                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6431                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6432                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6433                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6434                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6435                         }
6436                         break; // no screen processing, no bloom, skip it
6437                 }
6438
6439                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6440                 {
6441                         // render simple bloom effect
6442                         // copy the screen and shrink it and darken it for the bloom process
6443                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6444                         // make the bloom texture
6445                         R_Bloom_MakeTexture();
6446                 }
6447
6448 #if _MSC_VER >= 1400
6449 #define sscanf sscanf_s
6450 #endif
6451                 memset(uservecs, 0, sizeof(uservecs));
6452                 if (r_glsl_postprocess_uservec1_enable.integer)
6453                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6454                 if (r_glsl_postprocess_uservec2_enable.integer)
6455                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6456                 if (r_glsl_postprocess_uservec3_enable.integer)
6457                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6458                 if (r_glsl_postprocess_uservec4_enable.integer)
6459                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6460
6461                 R_ResetViewRendering2D();
6462                 GL_Color(1, 1, 1, 1);
6463                 GL_BlendFunc(GL_ONE, GL_ZERO);
6464
6465                 switch(vid.renderpath)
6466                 {
6467                 case RENDERPATH_GL20:
6468                 case RENDERPATH_GLES2:
6469                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6470                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6471                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6472                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6473                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6474                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6475                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6476                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6477                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6478                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6479                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6480                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6481                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6482                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6483                         break;
6484                 case RENDERPATH_D3D9:
6485 #ifdef SUPPORTD3D
6486                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6487                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6488                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6489                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6490                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6491                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6492                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6493                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6494                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6495                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6496                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6497                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6498                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6499                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6500                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6501 #endif
6502                         break;
6503                 case RENDERPATH_D3D10:
6504                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6505                         break;
6506                 case RENDERPATH_D3D11:
6507                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6508                         break;
6509                 case RENDERPATH_SOFT:
6510                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6511                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6512                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6513                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6514                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6515                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6516                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6517                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6518                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6519                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6520                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6521                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6522                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6523                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6524                         break;
6525                 default:
6526                         break;
6527                 }
6528                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6529                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6530                 break;
6531         case RENDERPATH_GL11:
6532         case RENDERPATH_GL13:
6533         case RENDERPATH_GLES1:
6534                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6535                 {
6536                         // apply a color tint to the whole view
6537                         R_ResetViewRendering2D();
6538                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6539                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6540                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6541                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6542                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6543                 }
6544                 break;
6545         }
6546 }
6547
6548 matrix4x4_t r_waterscrollmatrix;
6549
6550 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6551 {
6552         // Nehahra fog
6553         if (gamemode == GAME_NEHAHRA)
6554         {
6555                 if (gl_fogenable.integer)
6556                 {
6557                         r_refdef.oldgl_fogenable = true;
6558                         r_refdef.fog_density = gl_fogdensity.value;
6559                         r_refdef.fog_red = gl_fogred.value;
6560                         r_refdef.fog_green = gl_foggreen.value;
6561                         r_refdef.fog_blue = gl_fogblue.value;
6562                         r_refdef.fog_alpha = 1;
6563                         r_refdef.fog_start = 0;
6564                         r_refdef.fog_end = gl_skyclip.value;
6565                         r_refdef.fog_height = 1<<30;
6566                         r_refdef.fog_fadedepth = 128;
6567                 }
6568                 else if (r_refdef.oldgl_fogenable)
6569                 {
6570                         r_refdef.oldgl_fogenable = false;
6571                         r_refdef.fog_density = 0;
6572                         r_refdef.fog_red = 0;
6573                         r_refdef.fog_green = 0;
6574                         r_refdef.fog_blue = 0;
6575                         r_refdef.fog_alpha = 0;
6576                         r_refdef.fog_start = 0;
6577                         r_refdef.fog_end = 0;
6578                         r_refdef.fog_height = 1<<30;
6579                         r_refdef.fog_fadedepth = 128;
6580                 }
6581         }
6582
6583         // fog parms
6584         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6585         r_refdef.fog_start = max(0, r_refdef.fog_start);
6586         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6587
6588         if (r_refdef.fog_density && r_drawfog.integer)
6589         {
6590                 r_refdef.fogenabled = true;
6591                 // this is the point where the fog reaches 0.9986 alpha, which we
6592                 // consider a good enough cutoff point for the texture
6593                 // (0.9986 * 256 == 255.6)
6594                 if (r_fog_exp2.integer)
6595                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6596                 else
6597                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6598                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6599                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6600                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6601                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6602                         R_BuildFogHeightTexture();
6603                 // fog color was already set
6604                 // update the fog texture
6605                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6606                         R_BuildFogTexture();
6607                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6608                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6609         }
6610         else
6611                 r_refdef.fogenabled = false;
6612
6613         // fog color
6614         if (r_refdef.fog_density)
6615         {
6616                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6617                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6618                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6619
6620                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6621                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6622                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6623                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6624
6625                 {
6626                         vec3_t fogvec;
6627                         VectorCopy(r_refdef.fogcolor, fogvec);
6628                         //   color.rgb *= ContrastBoost * SceneBrightness;
6629                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6630                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6631                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6632                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6633                 }
6634         }
6635 }
6636
6637 void R_UpdateVariables(void)
6638 {
6639         R_Textures_Frame();
6640
6641         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6642
6643         r_refdef.farclip = r_farclip_base.value;
6644         if (r_refdef.scene.worldmodel)
6645                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6646         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6647
6648         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6649                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6650         r_refdef.polygonfactor = 0;
6651         r_refdef.polygonoffset = 0;
6652         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6653         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6654
6655         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6656         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6657         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6658         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6659         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6660         if (FAKELIGHT_ENABLED)
6661         {
6662                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6663         }
6664         if (r_showsurfaces.integer)
6665         {
6666                 r_refdef.scene.rtworld = false;
6667                 r_refdef.scene.rtworldshadows = false;
6668                 r_refdef.scene.rtdlight = false;
6669                 r_refdef.scene.rtdlightshadows = false;
6670                 r_refdef.lightmapintensity = 0;
6671         }
6672
6673         switch(vid.renderpath)
6674         {
6675         case RENDERPATH_GL20:
6676         case RENDERPATH_D3D9:
6677         case RENDERPATH_D3D10:
6678         case RENDERPATH_D3D11:
6679         case RENDERPATH_SOFT:
6680         case RENDERPATH_GLES2:
6681                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6682                 {
6683                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6684                         {
6685                                 // build GLSL gamma texture
6686 #define RAMPWIDTH 256
6687                                 unsigned short ramp[RAMPWIDTH * 3];
6688                                 unsigned char rampbgr[RAMPWIDTH][4];
6689                                 int i;
6690
6691                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6692
6693                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6694                                 for(i = 0; i < RAMPWIDTH; ++i)
6695                                 {
6696                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6697                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6698                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6699                                         rampbgr[i][3] = 0;
6700                                 }
6701                                 if (r_texture_gammaramps)
6702                                 {
6703                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6704                                 }
6705                                 else
6706                                 {
6707                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6708                                 }
6709                         }
6710                 }
6711                 else
6712                 {
6713                         // remove GLSL gamma texture
6714                 }
6715                 break;
6716         case RENDERPATH_GL11:
6717         case RENDERPATH_GL13:
6718         case RENDERPATH_GLES1:
6719                 break;
6720         }
6721 }
6722
6723 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6724 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6725 /*
6726 ================
6727 R_SelectScene
6728 ================
6729 */
6730 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6731         if( scenetype != r_currentscenetype ) {
6732                 // store the old scenetype
6733                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6734                 r_currentscenetype = scenetype;
6735                 // move in the new scene
6736                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6737         }
6738 }
6739
6740 /*
6741 ================
6742 R_GetScenePointer
6743 ================
6744 */
6745 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6746 {
6747         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6748         if( scenetype == r_currentscenetype ) {
6749                 return &r_refdef.scene;
6750         } else {
6751                 return &r_scenes_store[ scenetype ];
6752         }
6753 }
6754
6755 int R_SortEntities_Compare(const void *ap, const void *bp)
6756 {
6757         const entity_render_t *a = *(const entity_render_t **)ap;
6758         const entity_render_t *b = *(const entity_render_t **)bp;
6759
6760         // 1. compare model
6761         if(a->model < b->model)
6762                 return -1;
6763         if(a->model > b->model)
6764                 return +1;
6765
6766         // 2. compare skin
6767         // TODO possibly calculate the REAL skinnum here first using
6768         // skinscenes?
6769         if(a->skinnum < b->skinnum)
6770                 return -1;
6771         if(a->skinnum > b->skinnum)
6772                 return +1;
6773
6774         // everything we compared is equal
6775         return 0;
6776 }
6777 void R_SortEntities(void)
6778 {
6779         // below or equal 2 ents, sorting never gains anything
6780         if(r_refdef.scene.numentities <= 2)
6781                 return;
6782         // sort
6783         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6784 }
6785
6786 /*
6787 ================
6788 R_RenderView
6789 ================
6790 */
6791 int dpsoftrast_test;
6792 extern void R_Shadow_UpdateBounceGridTexture(void);
6793 extern cvar_t r_shadow_bouncegrid;
6794 void R_RenderView(void)
6795 {
6796         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6797
6798         dpsoftrast_test = r_test.integer;
6799
6800         if (r_timereport_active)
6801                 R_TimeReport("start");
6802         r_textureframe++; // used only by R_GetCurrentTexture
6803         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6804
6805         if(R_CompileShader_CheckStaticParms())
6806                 R_GLSL_Restart_f();
6807
6808         if (!r_drawentities.integer)
6809                 r_refdef.scene.numentities = 0;
6810         else if (r_sortentities.integer)
6811                 R_SortEntities();
6812
6813         R_AnimCache_ClearCache();
6814         R_FrameData_NewFrame();
6815
6816         /* adjust for stereo display */
6817         if(R_Stereo_Active())
6818         {
6819                 Matrix4x4_CreateFromQuakeEntity(&offsetmatrix, 0, r_stereo_separation.value * (0.5f - r_stereo_side), 0, 0, r_stereo_angle.value * (0.5f - r_stereo_side), 0, 1);
6820                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6821         }
6822
6823         if (r_refdef.view.isoverlay)
6824         {
6825                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6826                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6827                 R_TimeReport("depthclear");
6828
6829                 r_refdef.view.showdebug = false;
6830
6831                 r_waterstate.enabled = false;
6832                 r_waterstate.numwaterplanes = 0;
6833
6834                 R_RenderScene();
6835
6836                 r_refdef.view.matrix = originalmatrix;
6837
6838                 CHECKGLERROR
6839                 return;
6840         }
6841
6842         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6843         {
6844                 r_refdef.view.matrix = originalmatrix;
6845                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6846         }
6847
6848         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6849
6850         R_RenderView_UpdateViewVectors();
6851
6852         R_Shadow_UpdateWorldLightSelection();
6853
6854         R_Bloom_StartFrame();
6855         R_Water_StartFrame();
6856
6857         CHECKGLERROR
6858         if (r_timereport_active)
6859                 R_TimeReport("viewsetup");
6860
6861         R_ResetViewRendering3D();
6862
6863         if (r_refdef.view.clear || r_refdef.fogenabled)
6864         {
6865                 R_ClearScreen(r_refdef.fogenabled);
6866                 if (r_timereport_active)
6867                         R_TimeReport("viewclear");
6868         }
6869         r_refdef.view.clear = true;
6870
6871         // this produces a bloom texture to be used in R_BlendView() later
6872         if (r_bloomstate.hdr)
6873         {
6874                 R_HDR_RenderBloomTexture();
6875                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6876                 r_textureframe++; // used only by R_GetCurrentTexture
6877         }
6878
6879         r_refdef.view.showdebug = true;
6880
6881         R_View_Update();
6882         if (r_timereport_active)
6883                 R_TimeReport("visibility");
6884
6885         R_Shadow_UpdateBounceGridTexture();
6886         if (r_timereport_active && r_shadow_bouncegrid.integer)
6887                 R_TimeReport("bouncegrid");
6888
6889         r_waterstate.numwaterplanes = 0;
6890         if (r_waterstate.enabled)
6891                 R_RenderWaterPlanes();
6892
6893         R_RenderScene();
6894         r_waterstate.numwaterplanes = 0;
6895
6896         R_BlendView();
6897         if (r_timereport_active)
6898                 R_TimeReport("blendview");
6899
6900         GL_Scissor(0, 0, vid.width, vid.height);
6901         GL_ScissorTest(false);
6902
6903         r_refdef.view.matrix = originalmatrix;
6904
6905         CHECKGLERROR
6906 }
6907
6908 void R_RenderWaterPlanes(void)
6909 {
6910         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6911         {
6912                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6913                 if (r_timereport_active)
6914                         R_TimeReport("waterworld");
6915         }
6916
6917         // don't let sound skip if going slow
6918         if (r_refdef.scene.extraupdate)
6919                 S_ExtraUpdate ();
6920
6921         R_DrawModelsAddWaterPlanes();
6922         if (r_timereport_active)
6923                 R_TimeReport("watermodels");
6924
6925         if (r_waterstate.numwaterplanes)
6926         {
6927                 R_Water_ProcessPlanes();
6928                 if (r_timereport_active)
6929                         R_TimeReport("waterscenes");
6930         }
6931 }
6932
6933 extern void R_DrawLightningBeams (void);
6934 extern void VM_CL_AddPolygonsToMeshQueue (void);
6935 extern void R_DrawPortals (void);
6936 extern cvar_t cl_locs_show;
6937 static void R_DrawLocs(void);
6938 static void R_DrawEntityBBoxes(void);
6939 static void R_DrawModelDecals(void);
6940 extern void R_DrawModelShadows(void);
6941 extern void R_DrawModelShadowMaps(void);
6942 extern cvar_t cl_decals_newsystem;
6943 extern qboolean r_shadow_usingdeferredprepass;
6944 void R_RenderScene(void)
6945 {
6946         qboolean shadowmapping = false;
6947
6948         if (r_timereport_active)
6949                 R_TimeReport("beginscene");
6950
6951         r_refdef.stats.renders++;
6952
6953         R_UpdateFog();
6954
6955         // don't let sound skip if going slow
6956         if (r_refdef.scene.extraupdate)
6957                 S_ExtraUpdate ();
6958
6959         R_MeshQueue_BeginScene();
6960
6961         R_SkyStartFrame();
6962
6963         Matrix4x4_CreateTranslate(&r_waterscrollmatrix, sin(r_refdef.scene.time) * 0.025 * r_waterscroll.value, sin(r_refdef.scene.time * 0.8f) * 0.025 * r_waterscroll.value, 0);
6964
6965         if (r_timereport_active)
6966                 R_TimeReport("skystartframe");
6967
6968         if (cl.csqc_vidvars.drawworld)
6969         {
6970                 // don't let sound skip if going slow
6971                 if (r_refdef.scene.extraupdate)
6972                         S_ExtraUpdate ();
6973
6974                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6975                 {
6976                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6977                         if (r_timereport_active)
6978                                 R_TimeReport("worldsky");
6979                 }
6980
6981                 if (R_DrawBrushModelsSky() && r_timereport_active)
6982                         R_TimeReport("bmodelsky");
6983
6984                 if (skyrendermasked && skyrenderlater)
6985                 {
6986                         // we have to force off the water clipping plane while rendering sky
6987                         R_SetupView(false);
6988                         R_Sky();
6989                         R_SetupView(true);
6990                         if (r_timereport_active)
6991                                 R_TimeReport("sky");
6992                 }
6993         }
6994
6995         R_AnimCache_CacheVisibleEntities();
6996         if (r_timereport_active)
6997                 R_TimeReport("animation");
6998
6999         R_Shadow_PrepareLights();
7000         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7001                 R_Shadow_PrepareModelShadows();
7002         if (r_timereport_active)
7003                 R_TimeReport("preparelights");
7004
7005         if (R_Shadow_ShadowMappingEnabled())
7006                 shadowmapping = true;
7007
7008         if (r_shadow_usingdeferredprepass)
7009                 R_Shadow_DrawPrepass();
7010
7011         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7012         {
7013                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7014                 if (r_timereport_active)
7015                         R_TimeReport("worlddepth");
7016         }
7017         if (r_depthfirst.integer >= 2)
7018         {
7019                 R_DrawModelsDepth();
7020                 if (r_timereport_active)
7021                         R_TimeReport("modeldepth");
7022         }
7023
7024         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7025         {
7026                 R_DrawModelShadowMaps();
7027                 R_ResetViewRendering3D();
7028                 // don't let sound skip if going slow
7029                 if (r_refdef.scene.extraupdate)
7030                         S_ExtraUpdate ();
7031         }
7032
7033         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7034         {
7035                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7036                 if (r_timereport_active)
7037                         R_TimeReport("world");
7038         }
7039
7040         // don't let sound skip if going slow
7041         if (r_refdef.scene.extraupdate)
7042                 S_ExtraUpdate ();
7043
7044         R_DrawModels();
7045         if (r_timereport_active)
7046                 R_TimeReport("models");
7047
7048         // don't let sound skip if going slow
7049         if (r_refdef.scene.extraupdate)
7050                 S_ExtraUpdate ();
7051
7052         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7053         {
7054                 R_DrawModelShadows();
7055                 R_ResetViewRendering3D();
7056                 // don't let sound skip if going slow
7057                 if (r_refdef.scene.extraupdate)
7058                         S_ExtraUpdate ();
7059         }
7060
7061         if (!r_shadow_usingdeferredprepass)
7062         {
7063                 R_Shadow_DrawLights();
7064                 if (r_timereport_active)
7065                         R_TimeReport("rtlights");
7066         }
7067
7068         // don't let sound skip if going slow
7069         if (r_refdef.scene.extraupdate)
7070                 S_ExtraUpdate ();
7071
7072         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7073         {
7074                 R_DrawModelShadows();
7075                 R_ResetViewRendering3D();
7076                 // don't let sound skip if going slow
7077                 if (r_refdef.scene.extraupdate)
7078                         S_ExtraUpdate ();
7079         }
7080
7081         if (cl.csqc_vidvars.drawworld)
7082         {
7083                 if (cl_decals_newsystem.integer)
7084                 {
7085                         R_DrawModelDecals();
7086                         if (r_timereport_active)
7087                                 R_TimeReport("modeldecals");
7088                 }
7089                 else
7090                 {
7091                         R_DrawDecals();
7092                         if (r_timereport_active)
7093                                 R_TimeReport("decals");
7094                 }
7095
7096                 R_DrawParticles();
7097                 if (r_timereport_active)
7098                         R_TimeReport("particles");
7099
7100                 R_DrawExplosions();
7101                 if (r_timereport_active)
7102                         R_TimeReport("explosions");
7103
7104                 R_DrawLightningBeams();
7105                 if (r_timereport_active)
7106                         R_TimeReport("lightning");
7107         }
7108
7109         VM_CL_AddPolygonsToMeshQueue();
7110
7111         if (r_refdef.view.showdebug)
7112         {
7113                 if (cl_locs_show.integer)
7114                 {
7115                         R_DrawLocs();
7116                         if (r_timereport_active)
7117                                 R_TimeReport("showlocs");
7118                 }
7119
7120                 if (r_drawportals.integer)
7121                 {
7122                         R_DrawPortals();
7123                         if (r_timereport_active)
7124                                 R_TimeReport("portals");
7125                 }
7126
7127                 if (r_showbboxes.value > 0)
7128                 {
7129                         R_DrawEntityBBoxes();
7130                         if (r_timereport_active)
7131                                 R_TimeReport("bboxes");
7132                 }
7133         }
7134
7135         if (r_transparent.integer)
7136         {
7137                 R_MeshQueue_RenderTransparent();
7138                 if (r_timereport_active)
7139                         R_TimeReport("drawtrans");
7140         }
7141
7142         if (r_refdef.view.showdebug && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDebug && (r_showtris.value > 0 || r_shownormals.value != 0 || r_showcollisionbrushes.value > 0 || r_showoverdraw.value > 0))
7143         {
7144                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7145                 if (r_timereport_active)
7146                         R_TimeReport("worlddebug");
7147                 R_DrawModelsDebug();
7148                 if (r_timereport_active)
7149                         R_TimeReport("modeldebug");
7150         }
7151
7152         if (cl.csqc_vidvars.drawworld)
7153         {
7154                 R_Shadow_DrawCoronas();
7155                 if (r_timereport_active)
7156                         R_TimeReport("coronas");
7157         }
7158
7159 #if 0
7160         {
7161                 GL_DepthTest(false);
7162                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7163                 GL_Color(1, 1, 1, 1);
7164                 qglBegin(GL_POLYGON);
7165                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7166                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7167                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7168                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7169                 qglEnd();
7170                 qglBegin(GL_POLYGON);
7171                 qglVertex3f(r_refdef.view.frustumcorner[0][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[0][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[0][2] + 1000 * r_refdef.view.forward[2]);
7172                 qglVertex3f(r_refdef.view.frustumcorner[1][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[1][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[1][2] + 1000 * r_refdef.view.forward[2]);
7173                 qglVertex3f(r_refdef.view.frustumcorner[3][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[3][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[3][2] + 1000 * r_refdef.view.forward[2]);
7174                 qglVertex3f(r_refdef.view.frustumcorner[2][0] + 1000 * r_refdef.view.forward[0], r_refdef.view.frustumcorner[2][1] + 1000 * r_refdef.view.forward[1], r_refdef.view.frustumcorner[2][2] + 1000 * r_refdef.view.forward[2]);
7175                 qglEnd();
7176                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7177         }
7178 #endif
7179
7180         // don't let sound skip if going slow
7181         if (r_refdef.scene.extraupdate)
7182                 S_ExtraUpdate ();
7183
7184         R_ResetViewRendering2D();
7185 }
7186
7187 static const unsigned short bboxelements[36] =
7188 {
7189         5, 1, 3, 5, 3, 7,
7190         6, 2, 0, 6, 0, 4,
7191         7, 3, 2, 7, 2, 6,
7192         4, 0, 1, 4, 1, 5,
7193         4, 5, 7, 4, 7, 6,
7194         1, 0, 2, 1, 2, 3,
7195 };
7196
7197 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7198 {
7199         int i;
7200         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7201
7202         RSurf_ActiveWorldEntity();
7203
7204         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7205         GL_DepthMask(false);
7206         GL_DepthRange(0, 1);
7207         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7208 //      R_Mesh_ResetTextureState();
7209
7210         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7211         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7212         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7213         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7214         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7215         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7216         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7217         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7218         R_FillColors(color4f, 8, cr, cg, cb, ca);
7219         if (r_refdef.fogenabled)
7220         {
7221                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7222                 {
7223                         f1 = RSurf_FogVertex(v);
7224                         f2 = 1 - f1;
7225                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7226                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7227                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7228                 }
7229         }
7230         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7231         R_Mesh_ResetTextureState();
7232         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7233         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7234 }
7235
7236 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7237 {
7238         int i;
7239         float color[4];
7240         prvm_edict_t *edict;
7241         prvm_prog_t *prog_save = prog;
7242
7243         // this function draws bounding boxes of server entities
7244         if (!sv.active)
7245                 return;
7246
7247         GL_CullFace(GL_NONE);
7248         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7249
7250         prog = 0;
7251         SV_VM_Begin();
7252         for (i = 0;i < numsurfaces;i++)
7253         {
7254                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7255                 switch ((int)PRVM_serveredictfloat(edict, solid))
7256                 {
7257                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7258                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7259                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7260                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7261                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7262                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7263                 }
7264                 color[3] *= r_showbboxes.value;
7265                 color[3] = bound(0, color[3], 1);
7266                 GL_DepthTest(!r_showdisabledepthtest.integer);
7267                 GL_CullFace(r_refdef.view.cullface_front);
7268                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7269         }
7270         SV_VM_End();
7271         prog = prog_save;
7272 }
7273
7274 static void R_DrawEntityBBoxes(void)
7275 {
7276         int i;
7277         prvm_edict_t *edict;
7278         vec3_t center;
7279         prvm_prog_t *prog_save = prog;
7280
7281         // this function draws bounding boxes of server entities
7282         if (!sv.active)
7283                 return;
7284
7285         prog = 0;
7286         SV_VM_Begin();
7287         for (i = 0;i < prog->num_edicts;i++)
7288         {
7289                 edict = PRVM_EDICT_NUM(i);
7290                 if (edict->priv.server->free)
7291                         continue;
7292                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7293                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7294                         continue;
7295                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7296                         continue;
7297                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7298                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7299         }
7300         SV_VM_End();
7301         prog = prog_save;
7302 }
7303
7304 static const int nomodelelement3i[24] =
7305 {
7306         5, 2, 0,
7307         5, 1, 2,
7308         5, 0, 3,
7309         5, 3, 1,
7310         0, 2, 4,
7311         2, 1, 4,
7312         3, 0, 4,
7313         1, 3, 4
7314 };
7315
7316 static const unsigned short nomodelelement3s[24] =
7317 {
7318         5, 2, 0,
7319         5, 1, 2,
7320         5, 0, 3,
7321         5, 3, 1,
7322         0, 2, 4,
7323         2, 1, 4,
7324         3, 0, 4,
7325         1, 3, 4
7326 };
7327
7328 static const float nomodelvertex3f[6*3] =
7329 {
7330         -16,   0,   0,
7331          16,   0,   0,
7332           0, -16,   0,
7333           0,  16,   0,
7334           0,   0, -16,
7335           0,   0,  16
7336 };
7337
7338 static const float nomodelcolor4f[6*4] =
7339 {
7340         0.0f, 0.0f, 0.5f, 1.0f,
7341         0.0f, 0.0f, 0.5f, 1.0f,
7342         0.0f, 0.5f, 0.0f, 1.0f,
7343         0.0f, 0.5f, 0.0f, 1.0f,
7344         0.5f, 0.0f, 0.0f, 1.0f,
7345         0.5f, 0.0f, 0.0f, 1.0f
7346 };
7347
7348 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7349 {
7350         int i;
7351         float f1, f2, *c;
7352         float color4f[6*4];
7353
7354         RSurf_ActiveCustomEntity(&ent->matrix, &ent->inversematrix, ent->flags, ent->shadertime, ent->colormod[0], ent->colormod[1], ent->colormod[2], ent->alpha, 6, nomodelvertex3f, NULL, NULL, NULL, NULL, nomodelcolor4f, 8, nomodelelement3i, nomodelelement3s, false, false);
7355
7356         // this is only called once per entity so numsurfaces is always 1, and
7357         // surfacelist is always {0}, so this code does not handle batches
7358
7359         if (rsurface.ent_flags & RENDER_ADDITIVE)
7360         {
7361                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7362                 GL_DepthMask(false);
7363         }
7364         else if (rsurface.colormod[3] < 1)
7365         {
7366                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7367                 GL_DepthMask(false);
7368         }
7369         else
7370         {
7371                 GL_BlendFunc(GL_ONE, GL_ZERO);
7372                 GL_DepthMask(true);
7373         }
7374         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7375         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7376         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7377         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7378         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7379         for (i = 0, c = color4f;i < 6;i++, c += 4)
7380         {
7381                 c[0] *= rsurface.colormod[0];
7382                 c[1] *= rsurface.colormod[1];
7383                 c[2] *= rsurface.colormod[2];
7384                 c[3] *= rsurface.colormod[3];
7385         }
7386         if (r_refdef.fogenabled)
7387         {
7388                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7389                 {
7390                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7391                         f2 = 1 - f1;
7392                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7393                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7394                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7395                 }
7396         }
7397 //      R_Mesh_ResetTextureState();
7398         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7399         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7400         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7401 }
7402
7403 void R_DrawNoModel(entity_render_t *ent)
7404 {
7405         vec3_t org;
7406         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7407         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7408                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7409         else
7410                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7411 }
7412
7413 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7414 {
7415         vec3_t right1, right2, diff, normal;
7416
7417         VectorSubtract (org2, org1, normal);
7418
7419         // calculate 'right' vector for start
7420         VectorSubtract (r_refdef.view.origin, org1, diff);
7421         CrossProduct (normal, diff, right1);
7422         VectorNormalize (right1);
7423
7424         // calculate 'right' vector for end
7425         VectorSubtract (r_refdef.view.origin, org2, diff);
7426         CrossProduct (normal, diff, right2);
7427         VectorNormalize (right2);
7428
7429         vert[ 0] = org1[0] + width * right1[0];
7430         vert[ 1] = org1[1] + width * right1[1];
7431         vert[ 2] = org1[2] + width * right1[2];
7432         vert[ 3] = org1[0] - width * right1[0];
7433         vert[ 4] = org1[1] - width * right1[1];
7434         vert[ 5] = org1[2] - width * right1[2];
7435         vert[ 6] = org2[0] - width * right2[0];
7436         vert[ 7] = org2[1] - width * right2[1];
7437         vert[ 8] = org2[2] - width * right2[2];
7438         vert[ 9] = org2[0] + width * right2[0];
7439         vert[10] = org2[1] + width * right2[1];
7440         vert[11] = org2[2] + width * right2[2];
7441 }
7442
7443 void R_CalcSprite_Vertex3f(float *vertex3f, const vec3_t origin, const vec3_t left, const vec3_t up, float scalex1, float scalex2, float scaley1, float scaley2)
7444 {
7445         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7446         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7447         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7448         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7449         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7450         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7451         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7452         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7453         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7454         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7455         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7456         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7457 }
7458
7459 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7460 {
7461         int i;
7462         float *vertex3f;
7463         float v[3];
7464         VectorSet(v, x, y, z);
7465         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7466                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7467                         break;
7468         if (i == mesh->numvertices)
7469         {
7470                 if (mesh->numvertices < mesh->maxvertices)
7471                 {
7472                         VectorCopy(v, vertex3f);
7473                         mesh->numvertices++;
7474                 }
7475                 return mesh->numvertices;
7476         }
7477         else
7478                 return i;
7479 }
7480
7481 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7482 {
7483         int i;
7484         int *e, element[3];
7485         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7486         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7487         e = mesh->element3i + mesh->numtriangles * 3;
7488         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7489         {
7490                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7491                 if (mesh->numtriangles < mesh->maxtriangles)
7492                 {
7493                         *e++ = element[0];
7494                         *e++ = element[1];
7495                         *e++ = element[2];
7496                         mesh->numtriangles++;
7497                 }
7498                 element[1] = element[2];
7499         }
7500 }
7501
7502 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7503 {
7504         int i;
7505         int *e, element[3];
7506         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7507         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7508         e = mesh->element3i + mesh->numtriangles * 3;
7509         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7510         {
7511                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7512                 if (mesh->numtriangles < mesh->maxtriangles)
7513                 {
7514                         *e++ = element[0];
7515                         *e++ = element[1];
7516                         *e++ = element[2];
7517                         mesh->numtriangles++;
7518                 }
7519                 element[1] = element[2];
7520         }
7521 }
7522
7523 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7524 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7525 {
7526         int planenum, planenum2;
7527         int w;
7528         int tempnumpoints;
7529         mplane_t *plane, *plane2;
7530         double maxdist;
7531         double temppoints[2][256*3];
7532         // figure out how large a bounding box we need to properly compute this brush
7533         maxdist = 0;
7534         for (w = 0;w < numplanes;w++)
7535                 maxdist = max(maxdist, fabs(planes[w].dist));
7536         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7537         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7538         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7539         {
7540                 w = 0;
7541                 tempnumpoints = 4;
7542                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7543                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7544                 {
7545                         if (planenum2 == planenum)
7546                                 continue;
7547                         PolygonD_Divide(tempnumpoints, temppoints[w], plane2->normal[0], plane2->normal[1], plane2->normal[2], plane2->dist, R_MESH_PLANE_DIST_EPSILON, 0, NULL, NULL, 256, temppoints[!w], &tempnumpoints, NULL);
7548                         w = !w;
7549                 }
7550                 if (tempnumpoints < 3)
7551                         continue;
7552                 // generate elements forming a triangle fan for this polygon
7553                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7554         }
7555 }
7556
7557 static void R_Texture_AddLayer(texture_t *t, qboolean depthmask, int blendfunc1, int blendfunc2, texturelayertype_t type, rtexture_t *texture, const matrix4x4_t *matrix, float r, float g, float b, float a)
7558 {
7559         texturelayer_t *layer;
7560         layer = t->currentlayers + t->currentnumlayers++;
7561         layer->type = type;
7562         layer->depthmask = depthmask;
7563         layer->blendfunc1 = blendfunc1;
7564         layer->blendfunc2 = blendfunc2;
7565         layer->texture = texture;
7566         layer->texmatrix = *matrix;
7567         layer->color[0] = r;
7568         layer->color[1] = g;
7569         layer->color[2] = b;
7570         layer->color[3] = a;
7571 }
7572
7573 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7574 {
7575         if(parms[0] == 0 && parms[1] == 0)
7576                 return false;
7577         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7578                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7579                         return false;
7580         return true;
7581 }
7582
7583 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7584 {
7585         double index, f;
7586         index = parms[2] + rsurface.shadertime * parms[3];
7587         index -= floor(index);
7588         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7589         {
7590         default:
7591         case Q3WAVEFUNC_NONE:
7592         case Q3WAVEFUNC_NOISE:
7593         case Q3WAVEFUNC_COUNT:
7594                 f = 0;
7595                 break;
7596         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7597         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7598         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7599         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7600         case Q3WAVEFUNC_TRIANGLE:
7601                 index *= 4;
7602                 f = index - floor(index);
7603                 if (index < 1)
7604                 {
7605                         // f = f;
7606                 }
7607                 else if (index < 2)
7608                         f = 1 - f;
7609                 else if (index < 3)
7610                         f = -f;
7611                 else
7612                         f = -(1 - f);
7613                 break;
7614         }
7615         f = parms[0] + parms[1] * f;
7616         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7617                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7618         return (float) f;
7619 }
7620
7621 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7622 {
7623         int w, h, idx;
7624         double f;
7625         double offsetd[2];
7626         float tcmat[12];
7627         matrix4x4_t matrix, temp;
7628         switch(tcmod->tcmod)
7629         {
7630                 case Q3TCMOD_COUNT:
7631                 case Q3TCMOD_NONE:
7632                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7633                                 matrix = r_waterscrollmatrix;
7634                         else
7635                                 matrix = identitymatrix;
7636                         break;
7637                 case Q3TCMOD_ENTITYTRANSLATE:
7638                         // this is used in Q3 to allow the gamecode to control texcoord
7639                         // scrolling on the entity, which is not supported in darkplaces yet.
7640                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7641                         break;
7642                 case Q3TCMOD_ROTATE:
7643                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7644                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7645                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7646                         break;
7647                 case Q3TCMOD_SCALE:
7648                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7649                         break;
7650                 case Q3TCMOD_SCROLL:
7651                         // extra care is needed because of precision breakdown with large values of time
7652                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7653                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7654                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7655                         break;
7656                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7657                         w = (int) tcmod->parms[0];
7658                         h = (int) tcmod->parms[1];
7659                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7660                         f = f - floor(f);
7661                         idx = (int) floor(f * w * h);
7662                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7663                         break;
7664                 case Q3TCMOD_STRETCH:
7665                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7666                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7667                         break;
7668                 case Q3TCMOD_TRANSFORM:
7669                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7670                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7671                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7672                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7673                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7674                         break;
7675                 case Q3TCMOD_TURBULENT:
7676                         // this is handled in the RSurf_PrepareVertices function
7677                         matrix = identitymatrix;
7678                         break;
7679         }
7680         temp = *texmatrix;
7681         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7682 }
7683
7684 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7685 {
7686         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7687         char name[MAX_QPATH];
7688         skinframe_t *skinframe;
7689         unsigned char pixels[296*194];
7690         strlcpy(cache->name, skinname, sizeof(cache->name));
7691         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7692         if (developer_loading.integer)
7693                 Con_Printf("loading %s\n", name);
7694         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7695         if (!skinframe || !skinframe->base)
7696         {
7697                 unsigned char *f;
7698                 fs_offset_t filesize;
7699                 skinframe = NULL;
7700                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7701                 if (f)
7702                 {
7703                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7704                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7705                         Mem_Free(f);
7706                 }
7707         }
7708         cache->skinframe = skinframe;
7709 }
7710
7711 texture_t *R_GetCurrentTexture(texture_t *t)
7712 {
7713         int i;
7714         const entity_render_t *ent = rsurface.entity;
7715         dp_model_t *model = ent->model;
7716         q3shaderinfo_layer_tcmod_t *tcmod;
7717
7718         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7719                 return t->currentframe;
7720         t->update_lastrenderframe = r_textureframe;
7721         t->update_lastrenderentity = (void *)ent;
7722
7723         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7724                 t->camera_entity = ent->entitynumber;
7725         else
7726                 t->camera_entity = 0;
7727
7728         // switch to an alternate material if this is a q1bsp animated material
7729         {
7730                 texture_t *texture = t;
7731                 int s = rsurface.ent_skinnum;
7732                 if ((unsigned int)s >= (unsigned int)model->numskins)
7733                         s = 0;
7734                 if (model->skinscenes)
7735                 {
7736                         if (model->skinscenes[s].framecount > 1)
7737                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7738                         else
7739                                 s = model->skinscenes[s].firstframe;
7740                 }
7741                 if (s > 0)
7742                         t = t + s * model->num_surfaces;
7743                 if (t->animated)
7744                 {
7745                         // use an alternate animation if the entity's frame is not 0,
7746                         // and only if the texture has an alternate animation
7747                         if (rsurface.ent_alttextures && t->anim_total[1])
7748                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7749                         else
7750                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7751                 }
7752                 texture->currentframe = t;
7753         }
7754
7755         // update currentskinframe to be a qw skin or animation frame
7756         if (rsurface.ent_qwskin >= 0)
7757         {
7758                 i = rsurface.ent_qwskin;
7759                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7760                 {
7761                         r_qwskincache_size = cl.maxclients;
7762                         if (r_qwskincache)
7763                                 Mem_Free(r_qwskincache);
7764                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7765                 }
7766                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7767                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7768                 t->currentskinframe = r_qwskincache[i].skinframe;
7769                 if (t->currentskinframe == NULL)
7770                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7771         }
7772         else if (t->numskinframes >= 2)
7773                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7774         if (t->backgroundnumskinframes >= 2)
7775                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7776
7777         t->currentmaterialflags = t->basematerialflags;
7778         t->currentalpha = rsurface.colormod[3];
7779         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7780                 t->currentalpha *= r_wateralpha.value;
7781         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7782                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7783         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7784                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7785         if (!(rsurface.ent_flags & RENDER_LIGHT))
7786                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7787         else if (FAKELIGHT_ENABLED)
7788         {
7789                 // no modellight if using fakelight for the map
7790         }
7791         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7792         {
7793                 // pick a model lighting mode
7794                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7795                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7796                 else
7797                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7798         }
7799         if (rsurface.ent_flags & RENDER_ADDITIVE)
7800                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7801         else if (t->currentalpha < 1)
7802                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7803         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7804                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7805         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7806                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7807         if (t->backgroundnumskinframes)
7808                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7809         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7810         {
7811                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7812                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7813         }
7814         else
7815                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7816         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7817         {
7818                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7819                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7820         }
7821         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7822                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7823
7824         // there is no tcmod
7825         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7826         {
7827                 t->currenttexmatrix = r_waterscrollmatrix;
7828                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7829         }
7830         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7831         {
7832                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7833                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7834         }
7835
7836         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7837                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7838         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7839                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7840
7841         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7842         if (t->currentskinframe->qpixels)
7843                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7844         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7845         if (!t->basetexture)
7846                 t->basetexture = r_texture_notexture;
7847         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7848         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7849         t->nmaptexture = t->currentskinframe->nmap;
7850         if (!t->nmaptexture)
7851                 t->nmaptexture = r_texture_blanknormalmap;
7852         t->glosstexture = r_texture_black;
7853         t->glowtexture = t->currentskinframe->glow;
7854         t->fogtexture = t->currentskinframe->fog;
7855         t->reflectmasktexture = t->currentskinframe->reflect;
7856         if (t->backgroundnumskinframes)
7857         {
7858                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7859                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7860                 t->backgroundglosstexture = r_texture_black;
7861                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7862                 if (!t->backgroundnmaptexture)
7863                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7864         }
7865         else
7866         {
7867                 t->backgroundbasetexture = r_texture_white;
7868                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7869                 t->backgroundglosstexture = r_texture_black;
7870                 t->backgroundglowtexture = NULL;
7871         }
7872         t->specularpower = r_shadow_glossexponent.value;
7873         // TODO: store reference values for these in the texture?
7874         t->specularscale = 0;
7875         if (r_shadow_gloss.integer > 0)
7876         {
7877                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7878                 {
7879                         if (r_shadow_glossintensity.value > 0)
7880                         {
7881                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7882                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7883                                 t->specularscale = r_shadow_glossintensity.value;
7884                         }
7885                 }
7886                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7887                 {
7888                         t->glosstexture = r_texture_white;
7889                         t->backgroundglosstexture = r_texture_white;
7890                         t->specularscale = r_shadow_gloss2intensity.value;
7891                         t->specularpower = r_shadow_gloss2exponent.value;
7892                 }
7893         }
7894         t->specularscale *= t->specularscalemod;
7895         t->specularpower *= t->specularpowermod;
7896         t->rtlightambient = 0;
7897
7898         // lightmaps mode looks bad with dlights using actual texturing, so turn
7899         // off the colormap and glossmap, but leave the normalmap on as it still
7900         // accurately represents the shading involved
7901         if (gl_lightmaps.integer)
7902         {
7903                 t->basetexture = r_texture_grey128;
7904                 t->pantstexture = r_texture_black;
7905                 t->shirttexture = r_texture_black;
7906                 t->nmaptexture = r_texture_blanknormalmap;
7907                 t->glosstexture = r_texture_black;
7908                 t->glowtexture = NULL;
7909                 t->fogtexture = NULL;
7910                 t->reflectmasktexture = NULL;
7911                 t->backgroundbasetexture = NULL;
7912                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7913                 t->backgroundglosstexture = r_texture_black;
7914                 t->backgroundglowtexture = NULL;
7915                 t->specularscale = 0;
7916                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7917         }
7918
7919         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7920         VectorClear(t->dlightcolor);
7921         t->currentnumlayers = 0;
7922         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7923         {
7924                 int blendfunc1, blendfunc2;
7925                 qboolean depthmask;
7926                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7927                 {
7928                         blendfunc1 = GL_SRC_ALPHA;
7929                         blendfunc2 = GL_ONE;
7930                 }
7931                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7932                 {
7933                         blendfunc1 = GL_SRC_ALPHA;
7934                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7935                 }
7936                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7937                 {
7938                         blendfunc1 = t->customblendfunc[0];
7939                         blendfunc2 = t->customblendfunc[1];
7940                 }
7941                 else
7942                 {
7943                         blendfunc1 = GL_ONE;
7944                         blendfunc2 = GL_ZERO;
7945                 }
7946                 // don't colormod evilblend textures
7947                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7948                         VectorSet(t->lightmapcolor, 1, 1, 1);
7949                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7950                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7951                 {
7952                         // fullbright is not affected by r_refdef.lightmapintensity
7953                         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]);
7954                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7955                                 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]);
7956                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7957                                 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]);
7958                 }
7959                 else
7960                 {
7961                         vec3_t ambientcolor;
7962                         float colorscale;
7963                         // set the color tint used for lights affecting this surface
7964                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7965                         colorscale = 2;
7966                         // q3bsp has no lightmap updates, so the lightstylevalue that
7967                         // would normally be baked into the lightmap must be
7968                         // applied to the color
7969                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7970                         if (model->type == mod_brushq3)
7971                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7972                         colorscale *= r_refdef.lightmapintensity;
7973                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7974                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7975                         // basic lit geometry
7976                         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]);
7977                         // add pants/shirt if needed
7978                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7979                                 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]);
7980                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7981                                 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]);
7982                         // now add ambient passes if needed
7983                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7984                         {
7985                                 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]);
7986                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7987                                         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]);
7988                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7989                                         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]);
7990                         }
7991                 }
7992                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7993                         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]);
7994                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7995                 {
7996                         // if this is opaque use alpha blend which will darken the earlier
7997                         // passes cheaply.
7998                         //
7999                         // if this is an alpha blended material, all the earlier passes
8000                         // were darkened by fog already, so we only need to add the fog
8001                         // color ontop through the fog mask texture
8002                         //
8003                         // if this is an additive blended material, all the earlier passes
8004                         // were darkened by fog already, and we should not add fog color
8005                         // (because the background was not darkened, there is no fog color
8006                         // that was lost behind it).
8007                         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]);
8008                 }
8009         }
8010
8011         return t->currentframe;
8012 }
8013
8014 rsurfacestate_t rsurface;
8015
8016 void RSurf_ActiveWorldEntity(void)
8017 {
8018         dp_model_t *model = r_refdef.scene.worldmodel;
8019         //if (rsurface.entity == r_refdef.scene.worldentity)
8020         //      return;
8021         rsurface.entity = r_refdef.scene.worldentity;
8022         rsurface.skeleton = NULL;
8023         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8024         rsurface.ent_skinnum = 0;
8025         rsurface.ent_qwskin = -1;
8026         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8027         rsurface.shadertime = r_refdef.scene.time;
8028         rsurface.matrix = identitymatrix;
8029         rsurface.inversematrix = identitymatrix;
8030         rsurface.matrixscale = 1;
8031         rsurface.inversematrixscale = 1;
8032         R_EntityMatrix(&identitymatrix);
8033         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8034         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8035         rsurface.fograngerecip = r_refdef.fograngerecip;
8036         rsurface.fogheightfade = r_refdef.fogheightfade;
8037         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8038         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8039         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8040         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8041         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8042         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8043         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8044         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8045         rsurface.colormod[3] = 1;
8046         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);
8047         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8048         rsurface.frameblend[0].lerp = 1;
8049         rsurface.ent_alttextures = false;
8050         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8051         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8052         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8053         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8054         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8055         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8056         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8057         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8058         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8059         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8060         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8061         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8062         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8063         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8064         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8065         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8066         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8067         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8068         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8069         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8070         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8071         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8072         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8073         rsurface.modelelement3i = model->surfmesh.data_element3i;
8074         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8075         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8076         rsurface.modelelement3s = model->surfmesh.data_element3s;
8077         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8078         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8079         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8080         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8081         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8082         rsurface.modelsurfaces = model->data_surfaces;
8083         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8084         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8085         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8086         rsurface.modelgeneratedvertex = false;
8087         rsurface.batchgeneratedvertex = false;
8088         rsurface.batchfirstvertex = 0;
8089         rsurface.batchnumvertices = 0;
8090         rsurface.batchfirsttriangle = 0;
8091         rsurface.batchnumtriangles = 0;
8092         rsurface.batchvertex3f  = NULL;
8093         rsurface.batchvertex3f_vertexbuffer = NULL;
8094         rsurface.batchvertex3f_bufferoffset = 0;
8095         rsurface.batchsvector3f = NULL;
8096         rsurface.batchsvector3f_vertexbuffer = NULL;
8097         rsurface.batchsvector3f_bufferoffset = 0;
8098         rsurface.batchtvector3f = NULL;
8099         rsurface.batchtvector3f_vertexbuffer = NULL;
8100         rsurface.batchtvector3f_bufferoffset = 0;
8101         rsurface.batchnormal3f  = NULL;
8102         rsurface.batchnormal3f_vertexbuffer = NULL;
8103         rsurface.batchnormal3f_bufferoffset = 0;
8104         rsurface.batchlightmapcolor4f = NULL;
8105         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8106         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8107         rsurface.batchtexcoordtexture2f = NULL;
8108         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8109         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8110         rsurface.batchtexcoordlightmap2f = NULL;
8111         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8112         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8113         rsurface.batchvertexmesh = NULL;
8114         rsurface.batchvertexmeshbuffer = NULL;
8115         rsurface.batchvertex3fbuffer = NULL;
8116         rsurface.batchelement3i = NULL;
8117         rsurface.batchelement3i_indexbuffer = NULL;
8118         rsurface.batchelement3i_bufferoffset = 0;
8119         rsurface.batchelement3s = NULL;
8120         rsurface.batchelement3s_indexbuffer = NULL;
8121         rsurface.batchelement3s_bufferoffset = 0;
8122         rsurface.passcolor4f = NULL;
8123         rsurface.passcolor4f_vertexbuffer = NULL;
8124         rsurface.passcolor4f_bufferoffset = 0;
8125 }
8126
8127 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8128 {
8129         dp_model_t *model = ent->model;
8130         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8131         //      return;
8132         rsurface.entity = (entity_render_t *)ent;
8133         rsurface.skeleton = ent->skeleton;
8134         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8135         rsurface.ent_skinnum = ent->skinnum;
8136         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;
8137         rsurface.ent_flags = ent->flags;
8138         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8139         rsurface.matrix = ent->matrix;
8140         rsurface.inversematrix = ent->inversematrix;
8141         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8142         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8143         R_EntityMatrix(&rsurface.matrix);
8144         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8145         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8146         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8147         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8148         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8149         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8150         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8151         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8152         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8153         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8154         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8155         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8156         rsurface.colormod[3] = ent->alpha;
8157         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8158         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8159         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8160         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8161         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8162         if (ent->model->brush.submodel && !prepass)
8163         {
8164                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8165                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8166         }
8167         if (model->surfmesh.isanimated && model->AnimateVertices)
8168         {
8169                 if (ent->animcache_vertex3f)
8170                 {
8171                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8172                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8173                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8174                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8175                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8176                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8177                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8178                 }
8179                 else if (wanttangents)
8180                 {
8181                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8182                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8183                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8184                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8185                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8186                         rsurface.modelvertexmesh = NULL;
8187                         rsurface.modelvertexmeshbuffer = NULL;
8188                         rsurface.modelvertex3fbuffer = NULL;
8189                 }
8190                 else if (wantnormals)
8191                 {
8192                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8193                         rsurface.modelsvector3f = NULL;
8194                         rsurface.modeltvector3f = NULL;
8195                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8196                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8197                         rsurface.modelvertexmesh = NULL;
8198                         rsurface.modelvertexmeshbuffer = NULL;
8199                         rsurface.modelvertex3fbuffer = NULL;
8200                 }
8201                 else
8202                 {
8203                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8204                         rsurface.modelsvector3f = NULL;
8205                         rsurface.modeltvector3f = NULL;
8206                         rsurface.modelnormal3f = NULL;
8207                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8208                         rsurface.modelvertexmesh = NULL;
8209                         rsurface.modelvertexmeshbuffer = NULL;
8210                         rsurface.modelvertex3fbuffer = NULL;
8211                 }
8212                 rsurface.modelvertex3f_vertexbuffer = 0;
8213                 rsurface.modelvertex3f_bufferoffset = 0;
8214                 rsurface.modelsvector3f_vertexbuffer = 0;
8215                 rsurface.modelsvector3f_bufferoffset = 0;
8216                 rsurface.modeltvector3f_vertexbuffer = 0;
8217                 rsurface.modeltvector3f_bufferoffset = 0;
8218                 rsurface.modelnormal3f_vertexbuffer = 0;
8219                 rsurface.modelnormal3f_bufferoffset = 0;
8220                 rsurface.modelgeneratedvertex = true;
8221         }
8222         else
8223         {
8224                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8225                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8226                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8227                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8228                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8229                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8230                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8231                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8232                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8233                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8234                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8235                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8236                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8237                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8238                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8239                 rsurface.modelgeneratedvertex = false;
8240         }
8241         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8242         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8244         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8245         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8247         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8248         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8249         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8250         rsurface.modelelement3i = model->surfmesh.data_element3i;
8251         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8252         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8253         rsurface.modelelement3s = model->surfmesh.data_element3s;
8254         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8255         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8256         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8257         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8258         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8259         rsurface.modelsurfaces = model->data_surfaces;
8260         rsurface.batchgeneratedvertex = false;
8261         rsurface.batchfirstvertex = 0;
8262         rsurface.batchnumvertices = 0;
8263         rsurface.batchfirsttriangle = 0;
8264         rsurface.batchnumtriangles = 0;
8265         rsurface.batchvertex3f  = NULL;
8266         rsurface.batchvertex3f_vertexbuffer = NULL;
8267         rsurface.batchvertex3f_bufferoffset = 0;
8268         rsurface.batchsvector3f = NULL;
8269         rsurface.batchsvector3f_vertexbuffer = NULL;
8270         rsurface.batchsvector3f_bufferoffset = 0;
8271         rsurface.batchtvector3f = NULL;
8272         rsurface.batchtvector3f_vertexbuffer = NULL;
8273         rsurface.batchtvector3f_bufferoffset = 0;
8274         rsurface.batchnormal3f  = NULL;
8275         rsurface.batchnormal3f_vertexbuffer = NULL;
8276         rsurface.batchnormal3f_bufferoffset = 0;
8277         rsurface.batchlightmapcolor4f = NULL;
8278         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8279         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8280         rsurface.batchtexcoordtexture2f = NULL;
8281         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8282         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8283         rsurface.batchtexcoordlightmap2f = NULL;
8284         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8285         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8286         rsurface.batchvertexmesh = NULL;
8287         rsurface.batchvertexmeshbuffer = NULL;
8288         rsurface.batchvertex3fbuffer = NULL;
8289         rsurface.batchelement3i = NULL;
8290         rsurface.batchelement3i_indexbuffer = NULL;
8291         rsurface.batchelement3i_bufferoffset = 0;
8292         rsurface.batchelement3s = NULL;
8293         rsurface.batchelement3s_indexbuffer = NULL;
8294         rsurface.batchelement3s_bufferoffset = 0;
8295         rsurface.passcolor4f = NULL;
8296         rsurface.passcolor4f_vertexbuffer = NULL;
8297         rsurface.passcolor4f_bufferoffset = 0;
8298 }
8299
8300 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)
8301 {
8302         rsurface.entity = r_refdef.scene.worldentity;
8303         rsurface.skeleton = NULL;
8304         rsurface.ent_skinnum = 0;
8305         rsurface.ent_qwskin = -1;
8306         rsurface.ent_flags = entflags;
8307         rsurface.shadertime = r_refdef.scene.time - shadertime;
8308         rsurface.modelnumvertices = numvertices;
8309         rsurface.modelnumtriangles = numtriangles;
8310         rsurface.matrix = *matrix;
8311         rsurface.inversematrix = *inversematrix;
8312         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8313         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8314         R_EntityMatrix(&rsurface.matrix);
8315         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8316         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8317         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8318         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8319         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8320         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8321         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8322         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8323         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8324         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8325         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8326         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8327         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);
8328         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8329         rsurface.frameblend[0].lerp = 1;
8330         rsurface.ent_alttextures = false;
8331         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8332         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8333         if (wanttangents)
8334         {
8335                 rsurface.modelvertex3f = (float *)vertex3f;
8336                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8337                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8338                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8339         }
8340         else if (wantnormals)
8341         {
8342                 rsurface.modelvertex3f = (float *)vertex3f;
8343                 rsurface.modelsvector3f = NULL;
8344                 rsurface.modeltvector3f = NULL;
8345                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8346         }
8347         else
8348         {
8349                 rsurface.modelvertex3f = (float *)vertex3f;
8350                 rsurface.modelsvector3f = NULL;
8351                 rsurface.modeltvector3f = NULL;
8352                 rsurface.modelnormal3f = NULL;
8353         }
8354         rsurface.modelvertexmesh = NULL;
8355         rsurface.modelvertexmeshbuffer = NULL;
8356         rsurface.modelvertex3fbuffer = NULL;
8357         rsurface.modelvertex3f_vertexbuffer = 0;
8358         rsurface.modelvertex3f_bufferoffset = 0;
8359         rsurface.modelsvector3f_vertexbuffer = 0;
8360         rsurface.modelsvector3f_bufferoffset = 0;
8361         rsurface.modeltvector3f_vertexbuffer = 0;
8362         rsurface.modeltvector3f_bufferoffset = 0;
8363         rsurface.modelnormal3f_vertexbuffer = 0;
8364         rsurface.modelnormal3f_bufferoffset = 0;
8365         rsurface.modelgeneratedvertex = true;
8366         rsurface.modellightmapcolor4f  = (float *)color4f;
8367         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8368         rsurface.modellightmapcolor4f_bufferoffset = 0;
8369         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8370         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8371         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8372         rsurface.modeltexcoordlightmap2f  = NULL;
8373         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8374         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8375         rsurface.modelelement3i = (int *)element3i;
8376         rsurface.modelelement3i_indexbuffer = NULL;
8377         rsurface.modelelement3i_bufferoffset = 0;
8378         rsurface.modelelement3s = (unsigned short *)element3s;
8379         rsurface.modelelement3s_indexbuffer = NULL;
8380         rsurface.modelelement3s_bufferoffset = 0;
8381         rsurface.modellightmapoffsets = NULL;
8382         rsurface.modelsurfaces = NULL;
8383         rsurface.batchgeneratedvertex = false;
8384         rsurface.batchfirstvertex = 0;
8385         rsurface.batchnumvertices = 0;
8386         rsurface.batchfirsttriangle = 0;
8387         rsurface.batchnumtriangles = 0;
8388         rsurface.batchvertex3f  = NULL;
8389         rsurface.batchvertex3f_vertexbuffer = NULL;
8390         rsurface.batchvertex3f_bufferoffset = 0;
8391         rsurface.batchsvector3f = NULL;
8392         rsurface.batchsvector3f_vertexbuffer = NULL;
8393         rsurface.batchsvector3f_bufferoffset = 0;
8394         rsurface.batchtvector3f = NULL;
8395         rsurface.batchtvector3f_vertexbuffer = NULL;
8396         rsurface.batchtvector3f_bufferoffset = 0;
8397         rsurface.batchnormal3f  = NULL;
8398         rsurface.batchnormal3f_vertexbuffer = NULL;
8399         rsurface.batchnormal3f_bufferoffset = 0;
8400         rsurface.batchlightmapcolor4f = NULL;
8401         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8402         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8403         rsurface.batchtexcoordtexture2f = NULL;
8404         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8405         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8406         rsurface.batchtexcoordlightmap2f = NULL;
8407         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8408         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8409         rsurface.batchvertexmesh = NULL;
8410         rsurface.batchvertexmeshbuffer = NULL;
8411         rsurface.batchvertex3fbuffer = NULL;
8412         rsurface.batchelement3i = NULL;
8413         rsurface.batchelement3i_indexbuffer = NULL;
8414         rsurface.batchelement3i_bufferoffset = 0;
8415         rsurface.batchelement3s = NULL;
8416         rsurface.batchelement3s_indexbuffer = NULL;
8417         rsurface.batchelement3s_bufferoffset = 0;
8418         rsurface.passcolor4f = NULL;
8419         rsurface.passcolor4f_vertexbuffer = NULL;
8420         rsurface.passcolor4f_bufferoffset = 0;
8421
8422         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8423         {
8424                 if ((wantnormals || wanttangents) && !normal3f)
8425                 {
8426                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8427                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8428                 }
8429                 if (wanttangents && !svector3f)
8430                 {
8431                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8432                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8433                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8434                 }
8435         }
8436 }
8437
8438 float RSurf_FogPoint(const float *v)
8439 {
8440         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8441         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8442         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8443         float FogHeightFade = r_refdef.fogheightfade;
8444         float fogfrac;
8445         unsigned int fogmasktableindex;
8446         if (r_refdef.fogplaneviewabove)
8447                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8448         else
8449                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8450         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8451         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8452 }
8453
8454 float RSurf_FogVertex(const float *v)
8455 {
8456         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8457         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8458         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8459         float FogHeightFade = rsurface.fogheightfade;
8460         float fogfrac;
8461         unsigned int fogmasktableindex;
8462         if (r_refdef.fogplaneviewabove)
8463                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8464         else
8465                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8466         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8467         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8468 }
8469
8470 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8471 {
8472         int i;
8473         for (i = 0;i < numelements;i++)
8474                 outelement3i[i] = inelement3i[i] + adjust;
8475 }
8476
8477 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8478 extern cvar_t gl_vbo;
8479 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8480 {
8481         int deformindex;
8482         int firsttriangle;
8483         int numtriangles;
8484         int firstvertex;
8485         int endvertex;
8486         int numvertices;
8487         int surfacefirsttriangle;
8488         int surfacenumtriangles;
8489         int surfacefirstvertex;
8490         int surfaceendvertex;
8491         int surfacenumvertices;
8492         int batchnumvertices;
8493         int batchnumtriangles;
8494         int needsupdate;
8495         int i, j;
8496         qboolean gaps;
8497         qboolean dynamicvertex;
8498         float amplitude;
8499         float animpos;
8500         float scale;
8501         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8502         float waveparms[4];
8503         q3shaderinfo_deform_t *deform;
8504         const msurface_t *surface, *firstsurface;
8505         r_vertexmesh_t *vertexmesh;
8506         if (!texturenumsurfaces)
8507                 return;
8508         // find vertex range of this surface batch
8509         gaps = false;
8510         firstsurface = texturesurfacelist[0];
8511         firsttriangle = firstsurface->num_firsttriangle;
8512         batchnumvertices = 0;
8513         batchnumtriangles = 0;
8514         firstvertex = endvertex = firstsurface->num_firstvertex;
8515         for (i = 0;i < texturenumsurfaces;i++)
8516         {
8517                 surface = texturesurfacelist[i];
8518                 if (surface != firstsurface + i)
8519                         gaps = true;
8520                 surfacefirstvertex = surface->num_firstvertex;
8521                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8522                 surfacenumvertices = surface->num_vertices;
8523                 surfacenumtriangles = surface->num_triangles;
8524                 if (firstvertex > surfacefirstvertex)
8525                         firstvertex = surfacefirstvertex;
8526                 if (endvertex < surfaceendvertex)
8527                         endvertex = surfaceendvertex;
8528                 batchnumvertices += surfacenumvertices;
8529                 batchnumtriangles += surfacenumtriangles;
8530         }
8531
8532         // we now know the vertex range used, and if there are any gaps in it
8533         rsurface.batchfirstvertex = firstvertex;
8534         rsurface.batchnumvertices = endvertex - firstvertex;
8535         rsurface.batchfirsttriangle = firsttriangle;
8536         rsurface.batchnumtriangles = batchnumtriangles;
8537
8538         // this variable holds flags for which properties have been updated that
8539         // may require regenerating vertexmesh array...
8540         needsupdate = 0;
8541
8542         // check if any dynamic vertex processing must occur
8543         dynamicvertex = false;
8544
8545         // if there is a chance of animated vertex colors, it's a dynamic batch
8546         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8547         {
8548                 dynamicvertex = true;
8549                 batchneed |= BATCHNEED_NOGAPS;
8550                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8551         }
8552
8553         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8554         {
8555                 switch (deform->deform)
8556                 {
8557                 default:
8558                 case Q3DEFORM_PROJECTIONSHADOW:
8559                 case Q3DEFORM_TEXT0:
8560                 case Q3DEFORM_TEXT1:
8561                 case Q3DEFORM_TEXT2:
8562                 case Q3DEFORM_TEXT3:
8563                 case Q3DEFORM_TEXT4:
8564                 case Q3DEFORM_TEXT5:
8565                 case Q3DEFORM_TEXT6:
8566                 case Q3DEFORM_TEXT7:
8567                 case Q3DEFORM_NONE:
8568                         break;
8569                 case Q3DEFORM_AUTOSPRITE:
8570                         dynamicvertex = true;
8571                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8572                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8573                         break;
8574                 case Q3DEFORM_AUTOSPRITE2:
8575                         dynamicvertex = true;
8576                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8577                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8578                         break;
8579                 case Q3DEFORM_NORMAL:
8580                         dynamicvertex = true;
8581                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8582                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8583                         break;
8584                 case Q3DEFORM_WAVE:
8585                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8586                                 break; // if wavefunc is a nop, ignore this transform
8587                         dynamicvertex = true;
8588                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8589                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8590                         break;
8591                 case Q3DEFORM_BULGE:
8592                         dynamicvertex = true;
8593                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8594                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8595                         break;
8596                 case Q3DEFORM_MOVE:
8597                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8598                                 break; // if wavefunc is a nop, ignore this transform
8599                         dynamicvertex = true;
8600                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8601                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8602                         break;
8603                 }
8604         }
8605         switch(rsurface.texture->tcgen.tcgen)
8606         {
8607         default:
8608         case Q3TCGEN_TEXTURE:
8609                 break;
8610         case Q3TCGEN_LIGHTMAP:
8611                 dynamicvertex = true;
8612                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8613                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8614                 break;
8615         case Q3TCGEN_VECTOR:
8616                 dynamicvertex = true;
8617                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8618                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8619                 break;
8620         case Q3TCGEN_ENVIRONMENT:
8621                 dynamicvertex = true;
8622                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8623                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8624                 break;
8625         }
8626         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8627         {
8628                 dynamicvertex = true;
8629                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8630                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8631         }
8632
8633         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8634         {
8635                 dynamicvertex = true;
8636                 batchneed |= BATCHNEED_NOGAPS;
8637                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8638         }
8639
8640         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8641         {
8642                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8643                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8644                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8645                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8646                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8647                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8648                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8649         }
8650
8651         // when the model data has no vertex buffer (dynamic mesh), we need to
8652         // eliminate gaps
8653         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8654                 batchneed |= BATCHNEED_NOGAPS;
8655
8656         // if needsupdate, we have to do a dynamic vertex batch for sure
8657         if (needsupdate & batchneed)
8658                 dynamicvertex = true;
8659
8660         // see if we need to build vertexmesh from arrays
8661         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8662                 dynamicvertex = true;
8663
8664         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8665         // also some drivers strongly dislike firstvertex
8666         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8667                 dynamicvertex = true;
8668
8669         rsurface.batchvertex3f = rsurface.modelvertex3f;
8670         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8671         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8672         rsurface.batchsvector3f = rsurface.modelsvector3f;
8673         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8674         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8675         rsurface.batchtvector3f = rsurface.modeltvector3f;
8676         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8677         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8678         rsurface.batchnormal3f = rsurface.modelnormal3f;
8679         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8680         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8681         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8682         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8683         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8684         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8685         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8686         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8687         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8688         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8689         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8690         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8691         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8692         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8693         rsurface.batchelement3i = rsurface.modelelement3i;
8694         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8695         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8696         rsurface.batchelement3s = rsurface.modelelement3s;
8697         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8698         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8699
8700         // if any dynamic vertex processing has to occur in software, we copy the
8701         // entire surface list together before processing to rebase the vertices
8702         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8703         //
8704         // if any gaps exist and we do not have a static vertex buffer, we have to
8705         // copy the surface list together to avoid wasting upload bandwidth on the
8706         // vertices in the gaps.
8707         //
8708         // if gaps exist and we have a static vertex buffer, we still have to
8709         // combine the index buffer ranges into one dynamic index buffer.
8710         //
8711         // in all cases we end up with data that can be drawn in one call.
8712
8713         if (!dynamicvertex)
8714         {
8715                 // static vertex data, just set pointers...
8716                 rsurface.batchgeneratedvertex = false;
8717                 // if there are gaps, we want to build a combined index buffer,
8718                 // otherwise use the original static buffer with an appropriate offset
8719                 if (gaps)
8720                 {
8721                         // build a new triangle elements array for this batch
8722                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8723                         rsurface.batchfirsttriangle = 0;
8724                         numtriangles = 0;
8725                         for (i = 0;i < texturenumsurfaces;i++)
8726                         {
8727                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8728                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8729                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8730                                 numtriangles += surfacenumtriangles;
8731                         }
8732                         rsurface.batchelement3i_indexbuffer = NULL;
8733                         rsurface.batchelement3i_bufferoffset = 0;
8734                         rsurface.batchelement3s = NULL;
8735                         rsurface.batchelement3s_indexbuffer = NULL;
8736                         rsurface.batchelement3s_bufferoffset = 0;
8737                         if (endvertex <= 65536)
8738                         {
8739                                 // make a 16bit (unsigned short) index array if possible
8740                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8741                                 for (i = 0;i < numtriangles*3;i++)
8742                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8743                         }
8744                 }
8745                 return;
8746         }
8747
8748         // something needs software processing, do it for real...
8749         // we only directly handle separate array data in this case and then
8750         // generate interleaved data if needed...
8751         rsurface.batchgeneratedvertex = true;
8752
8753         // now copy the vertex data into a combined array and make an index array
8754         // (this is what Quake3 does all the time)
8755         //if (gaps || rsurface.batchfirstvertex)
8756         {
8757                 rsurface.batchvertex3fbuffer = NULL;
8758                 rsurface.batchvertexmesh = NULL;
8759                 rsurface.batchvertexmeshbuffer = NULL;
8760                 rsurface.batchvertex3f = NULL;
8761                 rsurface.batchvertex3f_vertexbuffer = NULL;
8762                 rsurface.batchvertex3f_bufferoffset = 0;
8763                 rsurface.batchsvector3f = NULL;
8764                 rsurface.batchsvector3f_vertexbuffer = NULL;
8765                 rsurface.batchsvector3f_bufferoffset = 0;
8766                 rsurface.batchtvector3f = NULL;
8767                 rsurface.batchtvector3f_vertexbuffer = NULL;
8768                 rsurface.batchtvector3f_bufferoffset = 0;
8769                 rsurface.batchnormal3f = NULL;
8770                 rsurface.batchnormal3f_vertexbuffer = NULL;
8771                 rsurface.batchnormal3f_bufferoffset = 0;
8772                 rsurface.batchlightmapcolor4f = NULL;
8773                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8774                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8775                 rsurface.batchtexcoordtexture2f = NULL;
8776                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8777                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8778                 rsurface.batchtexcoordlightmap2f = NULL;
8779                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8780                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8781                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8782                 rsurface.batchelement3i_indexbuffer = NULL;
8783                 rsurface.batchelement3i_bufferoffset = 0;
8784                 rsurface.batchelement3s = NULL;
8785                 rsurface.batchelement3s_indexbuffer = NULL;
8786                 rsurface.batchelement3s_bufferoffset = 0;
8787                 // we'll only be setting up certain arrays as needed
8788                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8789                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8790                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8791                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8792                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8793                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8794                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8795                 {
8796                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8797                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8798                 }
8799                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8800                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8801                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8802                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8803                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8804                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8805                 numvertices = 0;
8806                 numtriangles = 0;
8807                 for (i = 0;i < texturenumsurfaces;i++)
8808                 {
8809                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8810                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8811                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8812                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8813                         // copy only the data requested
8814                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8815                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8816                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8817                         {
8818                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8819                                 {
8820                                         if (rsurface.batchvertex3f)
8821                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8822                                         else
8823                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8824                                 }
8825                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8826                                 {
8827                                         if (rsurface.modelnormal3f)
8828                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8829                                         else
8830                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8831                                 }
8832                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8833                                 {
8834                                         if (rsurface.modelsvector3f)
8835                                         {
8836                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8837                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8838                                         }
8839                                         else
8840                                         {
8841                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8842                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8843                                         }
8844                                 }
8845                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8846                                 {
8847                                         if (rsurface.modellightmapcolor4f)
8848                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8849                                         else
8850                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8851                                 }
8852                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8853                                 {
8854                                         if (rsurface.modeltexcoordtexture2f)
8855                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8856                                         else
8857                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8858                                 }
8859                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8860                                 {
8861                                         if (rsurface.modeltexcoordlightmap2f)
8862                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8863                                         else
8864                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8865                                 }
8866                         }
8867                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8868                         numvertices += surfacenumvertices;
8869                         numtriangles += surfacenumtriangles;
8870                 }
8871
8872                 // generate a 16bit index array as well if possible
8873                 // (in general, dynamic batches fit)
8874                 if (numvertices <= 65536)
8875                 {
8876                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8877                         for (i = 0;i < numtriangles*3;i++)
8878                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8879                 }
8880
8881                 // since we've copied everything, the batch now starts at 0
8882                 rsurface.batchfirstvertex = 0;
8883                 rsurface.batchnumvertices = batchnumvertices;
8884                 rsurface.batchfirsttriangle = 0;
8885                 rsurface.batchnumtriangles = batchnumtriangles;
8886         }
8887
8888         // q1bsp surfaces rendered in vertex color mode have to have colors
8889         // calculated based on lightstyles
8890         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8891         {
8892                 // generate color arrays for the surfaces in this list
8893                 int c[4];
8894                 int scale;
8895                 int size3;
8896                 const int *offsets;
8897                 const unsigned char *lm;
8898                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8899                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8900                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8901                 numvertices = 0;
8902                 for (i = 0;i < texturenumsurfaces;i++)
8903                 {
8904                         surface = texturesurfacelist[i];
8905                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8906                         surfacenumvertices = surface->num_vertices;
8907                         if (surface->lightmapinfo->samples)
8908                         {
8909                                 for (j = 0;j < surfacenumvertices;j++)
8910                                 {
8911                                         lm = surface->lightmapinfo->samples + offsets[j];
8912                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8913                                         VectorScale(lm, scale, c);
8914                                         if (surface->lightmapinfo->styles[1] != 255)
8915                                         {
8916                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8917                                                 lm += size3;
8918                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8919                                                 VectorMA(c, scale, lm, c);
8920                                                 if (surface->lightmapinfo->styles[2] != 255)
8921                                                 {
8922                                                         lm += size3;
8923                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8924                                                         VectorMA(c, scale, lm, c);
8925                                                         if (surface->lightmapinfo->styles[3] != 255)
8926                                                         {
8927                                                                 lm += size3;
8928                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8929                                                                 VectorMA(c, scale, lm, c);
8930                                                         }
8931                                                 }
8932                                         }
8933                                         c[0] >>= 7;
8934                                         c[1] >>= 7;
8935                                         c[2] >>= 7;
8936                                         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);
8937                                         numvertices++;
8938                                 }
8939                         }
8940                         else
8941                         {
8942                                 for (j = 0;j < surfacenumvertices;j++)
8943                                 {
8944                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8945                                         numvertices++;
8946                                 }
8947                         }
8948                 }
8949         }
8950
8951         // if vertices are deformed (sprite flares and things in maps, possibly
8952         // water waves, bulges and other deformations), modify the copied vertices
8953         // in place
8954         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8955         {
8956                 switch (deform->deform)
8957                 {
8958                 default:
8959                 case Q3DEFORM_PROJECTIONSHADOW:
8960                 case Q3DEFORM_TEXT0:
8961                 case Q3DEFORM_TEXT1:
8962                 case Q3DEFORM_TEXT2:
8963                 case Q3DEFORM_TEXT3:
8964                 case Q3DEFORM_TEXT4:
8965                 case Q3DEFORM_TEXT5:
8966                 case Q3DEFORM_TEXT6:
8967                 case Q3DEFORM_TEXT7:
8968                 case Q3DEFORM_NONE:
8969                         break;
8970                 case Q3DEFORM_AUTOSPRITE:
8971                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8972                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8973                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8974                         VectorNormalize(newforward);
8975                         VectorNormalize(newright);
8976                         VectorNormalize(newup);
8977 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8978 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8979 //                      rsurface.batchvertex3f_bufferoffset = 0;
8980 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8981 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8982 //                      rsurface.batchsvector3f_bufferoffset = 0;
8983 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8984 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8985 //                      rsurface.batchtvector3f_bufferoffset = 0;
8986 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8987 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8988 //                      rsurface.batchnormal3f_bufferoffset = 0;
8989                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8990                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8991                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8992                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8993                                 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);
8994                         // a single autosprite surface can contain multiple sprites...
8995                         for (j = 0;j < batchnumvertices - 3;j += 4)
8996                         {
8997                                 VectorClear(center);
8998                                 for (i = 0;i < 4;i++)
8999                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9000                                 VectorScale(center, 0.25f, center);
9001                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9002                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9003                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9004                                 for (i = 0;i < 4;i++)
9005                                 {
9006                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9007                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9008                                 }
9009                         }
9010                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9011                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9012                         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);
9013                         break;
9014                 case Q3DEFORM_AUTOSPRITE2:
9015                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9016                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9017                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9018                         VectorNormalize(newforward);
9019                         VectorNormalize(newright);
9020                         VectorNormalize(newup);
9021 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9022 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9023 //                      rsurface.batchvertex3f_bufferoffset = 0;
9024                         {
9025                                 const float *v1, *v2;
9026                                 vec3_t start, end;
9027                                 float f, l;
9028                                 struct
9029                                 {
9030                                         float length2;
9031                                         const float *v1;
9032                                         const float *v2;
9033                                 }
9034                                 shortest[2];
9035                                 memset(shortest, 0, sizeof(shortest));
9036                                 // a single autosprite surface can contain multiple sprites...
9037                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9038                                 {
9039                                         VectorClear(center);
9040                                         for (i = 0;i < 4;i++)
9041                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9042                                         VectorScale(center, 0.25f, center);
9043                                         // find the two shortest edges, then use them to define the
9044                                         // axis vectors for rotating around the central axis
9045                                         for (i = 0;i < 6;i++)
9046                                         {
9047                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9048                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9049                                                 l = VectorDistance2(v1, v2);
9050                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9051                                                 if (v1[2] != v2[2])
9052                                                         l += (1.0f / 1024.0f);
9053                                                 if (shortest[0].length2 > l || i == 0)
9054                                                 {
9055                                                         shortest[1] = shortest[0];
9056                                                         shortest[0].length2 = l;
9057                                                         shortest[0].v1 = v1;
9058                                                         shortest[0].v2 = v2;
9059                                                 }
9060                                                 else if (shortest[1].length2 > l || i == 1)
9061                                                 {
9062                                                         shortest[1].length2 = l;
9063                                                         shortest[1].v1 = v1;
9064                                                         shortest[1].v2 = v2;
9065                                                 }
9066                                         }
9067                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9068                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9069                                         // this calculates the right vector from the shortest edge
9070                                         // and the up vector from the edge midpoints
9071                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9072                                         VectorNormalize(right);
9073                                         VectorSubtract(end, start, up);
9074                                         VectorNormalize(up);
9075                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9076                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9077                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9078                                         VectorNegate(forward, forward);
9079                                         VectorReflect(forward, 0, up, forward);
9080                                         VectorNormalize(forward);
9081                                         CrossProduct(up, forward, newright);
9082                                         VectorNormalize(newright);
9083                                         // rotate the quad around the up axis vector, this is made
9084                                         // especially easy by the fact we know the quad is flat,
9085                                         // so we only have to subtract the center position and
9086                                         // measure distance along the right vector, and then
9087                                         // multiply that by the newright vector and add back the
9088                                         // center position
9089                                         // we also need to subtract the old position to undo the
9090                                         // displacement from the center, which we do with a
9091                                         // DotProduct, the subtraction/addition of center is also
9092                                         // optimized into DotProducts here
9093                                         l = DotProduct(right, center);
9094                                         for (i = 0;i < 4;i++)
9095                                         {
9096                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9097                                                 f = DotProduct(right, v1) - l;
9098                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9099                                         }
9100                                 }
9101                         }
9102                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9103                         {
9104 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9105 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9106 //                              rsurface.batchnormal3f_bufferoffset = 0;
9107                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9108                         }
9109                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9110                         {
9111 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9112 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9113 //                              rsurface.batchsvector3f_bufferoffset = 0;
9114 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9115 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9116 //                              rsurface.batchtvector3f_bufferoffset = 0;
9117                                 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);
9118                         }
9119                         break;
9120                 case Q3DEFORM_NORMAL:
9121                         // deform the normals to make reflections wavey
9122                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9123                         rsurface.batchnormal3f_vertexbuffer = NULL;
9124                         rsurface.batchnormal3f_bufferoffset = 0;
9125                         for (j = 0;j < batchnumvertices;j++)
9126                         {
9127                                 float vertex[3];
9128                                 float *normal = rsurface.batchnormal3f + 3*j;
9129                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9130                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9131                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9132                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9133                                 VectorNormalize(normal);
9134                         }
9135                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9136                         {
9137 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9138 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9139 //                              rsurface.batchsvector3f_bufferoffset = 0;
9140 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9141 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9142 //                              rsurface.batchtvector3f_bufferoffset = 0;
9143                                 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);
9144                         }
9145                         break;
9146                 case Q3DEFORM_WAVE:
9147                         // deform vertex array to make wavey water and flags and such
9148                         waveparms[0] = deform->waveparms[0];
9149                         waveparms[1] = deform->waveparms[1];
9150                         waveparms[2] = deform->waveparms[2];
9151                         waveparms[3] = deform->waveparms[3];
9152                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9153                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9154                         // this is how a divisor of vertex influence on deformation
9155                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9156                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9157 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9158 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9159 //                      rsurface.batchvertex3f_bufferoffset = 0;
9160 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9161 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9162 //                      rsurface.batchnormal3f_bufferoffset = 0;
9163                         for (j = 0;j < batchnumvertices;j++)
9164                         {
9165                                 // if the wavefunc depends on time, evaluate it per-vertex
9166                                 if (waveparms[3])
9167                                 {
9168                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9169                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9170                                 }
9171                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9172                         }
9173                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9174                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9175                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9176                         {
9177 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9178 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9179 //                              rsurface.batchsvector3f_bufferoffset = 0;
9180 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9181 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9182 //                              rsurface.batchtvector3f_bufferoffset = 0;
9183                                 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);
9184                         }
9185                         break;
9186                 case Q3DEFORM_BULGE:
9187                         // deform vertex array to make the surface have moving bulges
9188 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9189 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9190 //                      rsurface.batchvertex3f_bufferoffset = 0;
9191 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9192 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9193 //                      rsurface.batchnormal3f_bufferoffset = 0;
9194                         for (j = 0;j < batchnumvertices;j++)
9195                         {
9196                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9197                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9198                         }
9199                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9200                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9201                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9202                         {
9203 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9204 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9205 //                              rsurface.batchsvector3f_bufferoffset = 0;
9206 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9207 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9208 //                              rsurface.batchtvector3f_bufferoffset = 0;
9209                                 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);
9210                         }
9211                         break;
9212                 case Q3DEFORM_MOVE:
9213                         // deform vertex array
9214                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9215                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9216                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9217                         VectorScale(deform->parms, scale, waveparms);
9218 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9219 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9220 //                      rsurface.batchvertex3f_bufferoffset = 0;
9221                         for (j = 0;j < batchnumvertices;j++)
9222                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9223                         break;
9224                 }
9225         }
9226
9227         // generate texcoords based on the chosen texcoord source
9228         switch(rsurface.texture->tcgen.tcgen)
9229         {
9230         default:
9231         case Q3TCGEN_TEXTURE:
9232                 break;
9233         case Q3TCGEN_LIGHTMAP:
9234 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9235 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9236 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9237                 if (rsurface.batchtexcoordlightmap2f)
9238                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9239                 break;
9240         case Q3TCGEN_VECTOR:
9241 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9242 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9243 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9244                 for (j = 0;j < batchnumvertices;j++)
9245                 {
9246                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9247                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9248                 }
9249                 break;
9250         case Q3TCGEN_ENVIRONMENT:
9251                 // make environment reflections using a spheremap
9252                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9253                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9254                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9255                 for (j = 0;j < batchnumvertices;j++)
9256                 {
9257                         // identical to Q3A's method, but executed in worldspace so
9258                         // carried models can be shiny too
9259
9260                         float viewer[3], d, reflected[3], worldreflected[3];
9261
9262                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9263                         // VectorNormalize(viewer);
9264
9265                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9266
9267                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9268                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9269                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9270                         // note: this is proportinal to viewer, so we can normalize later
9271
9272                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9273                         VectorNormalize(worldreflected);
9274
9275                         // note: this sphere map only uses world x and z!
9276                         // so positive and negative y will LOOK THE SAME.
9277                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9278                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9279                 }
9280                 break;
9281         }
9282         // the only tcmod that needs software vertex processing is turbulent, so
9283         // check for it here and apply the changes if needed
9284         // and we only support that as the first one
9285         // (handling a mixture of turbulent and other tcmods would be problematic
9286         //  without punting it entirely to a software path)
9287         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9288         {
9289                 amplitude = rsurface.texture->tcmods[0].parms[1];
9290                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9291 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9293 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9294                 for (j = 0;j < batchnumvertices;j++)
9295                 {
9296                         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);
9297                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9298                 }
9299         }
9300
9301         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9302         {
9303                 // convert the modified arrays to vertex structs
9304 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9305 //              rsurface.batchvertexmeshbuffer = NULL;
9306                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9307                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9308                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9309                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9310                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9311                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9312                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9313                 {
9314                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9315                         {
9316                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9317                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9318                         }
9319                 }
9320                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9321                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9322                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9323                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9324                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9325                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9326                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9327                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9328                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9329         }
9330 }
9331
9332 void RSurf_DrawBatch(void)
9333 {
9334         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9335         // through the pipeline, killing it earlier in the pipeline would have
9336         // per-surface overhead rather than per-batch overhead, so it's best to
9337         // reject it here, before it hits glDraw.
9338         if (rsurface.batchnumtriangles == 0)
9339                 return;
9340 #if 0
9341         // batch debugging code
9342         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9343         {
9344                 int i;
9345                 int j;
9346                 int c;
9347                 const int *e;
9348                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9349                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9350                 {
9351                         c = e[i];
9352                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9353                         {
9354                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9355                                 {
9356                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9357                                                 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);
9358                                         break;
9359                                 }
9360                         }
9361                 }
9362         }
9363 #endif
9364         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);
9365 }
9366
9367 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9368 {
9369         // pick the closest matching water plane
9370         int planeindex, vertexindex, bestplaneindex = -1;
9371         float d, bestd;
9372         vec3_t vert;
9373         const float *v;
9374         r_waterstate_waterplane_t *p;
9375         qboolean prepared = false;
9376         bestd = 0;
9377         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9378         {
9379                 if(p->camera_entity != rsurface.texture->camera_entity)
9380                         continue;
9381                 d = 0;
9382                 if(!prepared)
9383                 {
9384                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9385                         prepared = true;
9386                         if(rsurface.batchnumvertices == 0)
9387                                 break;
9388                 }
9389                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9390                 {
9391                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9392                         d += fabs(PlaneDiff(vert, &p->plane));
9393                 }
9394                 if (bestd > d || bestplaneindex < 0)
9395                 {
9396                         bestd = d;
9397                         bestplaneindex = planeindex;
9398                 }
9399         }
9400         return bestplaneindex;
9401         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9402         // this situation though, as it might be better to render single larger
9403         // batches with useless stuff (backface culled for example) than to
9404         // render multiple smaller batches
9405 }
9406
9407 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9408 {
9409         int i;
9410         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9411         rsurface.passcolor4f_vertexbuffer = 0;
9412         rsurface.passcolor4f_bufferoffset = 0;
9413         for (i = 0;i < rsurface.batchnumvertices;i++)
9414                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9415 }
9416
9417 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9418 {
9419         int i;
9420         float f;
9421         const float *v;
9422         const float *c;
9423         float *c2;
9424         if (rsurface.passcolor4f)
9425         {
9426                 // generate color arrays
9427                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9428                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9429                 rsurface.passcolor4f_vertexbuffer = 0;
9430                 rsurface.passcolor4f_bufferoffset = 0;
9431                 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)
9432                 {
9433                         f = RSurf_FogVertex(v);
9434                         c2[0] = c[0] * f;
9435                         c2[1] = c[1] * f;
9436                         c2[2] = c[2] * f;
9437                         c2[3] = c[3];
9438                 }
9439         }
9440         else
9441         {
9442                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9443                 rsurface.passcolor4f_vertexbuffer = 0;
9444                 rsurface.passcolor4f_bufferoffset = 0;
9445                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9446                 {
9447                         f = RSurf_FogVertex(v);
9448                         c2[0] = f;
9449                         c2[1] = f;
9450                         c2[2] = f;
9451                         c2[3] = 1;
9452                 }
9453         }
9454 }
9455
9456 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9457 {
9458         int i;
9459         float f;
9460         const float *v;
9461         const float *c;
9462         float *c2;
9463         if (!rsurface.passcolor4f)
9464                 return;
9465         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9466         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9467         rsurface.passcolor4f_vertexbuffer = 0;
9468         rsurface.passcolor4f_bufferoffset = 0;
9469         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)
9470         {
9471                 f = RSurf_FogVertex(v);
9472                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9473                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9474                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9475                 c2[3] = c[3];
9476         }
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9480 {
9481         int i;
9482         const float *c;
9483         float *c2;
9484         if (!rsurface.passcolor4f)
9485                 return;
9486         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9487         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9488         rsurface.passcolor4f_vertexbuffer = 0;
9489         rsurface.passcolor4f_bufferoffset = 0;
9490         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9491         {
9492                 c2[0] = c[0] * r;
9493                 c2[1] = c[1] * g;
9494                 c2[2] = c[2] * b;
9495                 c2[3] = c[3] * a;
9496         }
9497 }
9498
9499 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9500 {
9501         int i;
9502         const float *c;
9503         float *c2;
9504         if (!rsurface.passcolor4f)
9505                 return;
9506         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9507         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9508         rsurface.passcolor4f_vertexbuffer = 0;
9509         rsurface.passcolor4f_bufferoffset = 0;
9510         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9511         {
9512                 c2[0] = c[0] + r_refdef.scene.ambient;
9513                 c2[1] = c[1] + r_refdef.scene.ambient;
9514                 c2[2] = c[2] + r_refdef.scene.ambient;
9515                 c2[3] = c[3];
9516         }
9517 }
9518
9519 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9520 {
9521         // TODO: optimize
9522         rsurface.passcolor4f = NULL;
9523         rsurface.passcolor4f_vertexbuffer = 0;
9524         rsurface.passcolor4f_bufferoffset = 0;
9525         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9526         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9527         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9528         GL_Color(r, g, b, a);
9529         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9530         RSurf_DrawBatch();
9531 }
9532
9533 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9534 {
9535         // TODO: optimize applyfog && applycolor case
9536         // just apply fog if necessary, and tint the fog color array if necessary
9537         rsurface.passcolor4f = NULL;
9538         rsurface.passcolor4f_vertexbuffer = 0;
9539         rsurface.passcolor4f_bufferoffset = 0;
9540         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9541         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9542         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9543         GL_Color(r, g, b, a);
9544         RSurf_DrawBatch();
9545 }
9546
9547 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9548 {
9549         // TODO: optimize
9550         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9551         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9552         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9553         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9554         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9555         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9556         GL_Color(r, g, b, a);
9557         RSurf_DrawBatch();
9558 }
9559
9560 static void RSurf_DrawBatch_GL11_ClampColor(void)
9561 {
9562         int i;
9563         const float *c1;
9564         float *c2;
9565         if (!rsurface.passcolor4f)
9566                 return;
9567         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9568         {
9569                 c2[0] = bound(0.0f, c1[0], 1.0f);
9570                 c2[1] = bound(0.0f, c1[1], 1.0f);
9571                 c2[2] = bound(0.0f, c1[2], 1.0f);
9572                 c2[3] = bound(0.0f, c1[3], 1.0f);
9573         }
9574 }
9575
9576 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9577 {
9578         int i;
9579         float f;
9580         const float *v;
9581         const float *n;
9582         float *c;
9583         //vec3_t eyedir;
9584
9585         // fake shading
9586         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9587         rsurface.passcolor4f_vertexbuffer = 0;
9588         rsurface.passcolor4f_bufferoffset = 0;
9589         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)
9590         {
9591                 f = -DotProduct(r_refdef.view.forward, n);
9592                 f = max(0, f);
9593                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9594                 f *= r_refdef.lightmapintensity;
9595                 Vector4Set(c, f, f, f, 1);
9596         }
9597 }
9598
9599 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9600 {
9601         RSurf_DrawBatch_GL11_ApplyFakeLight();
9602         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9603         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9604         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9605         GL_Color(r, g, b, a);
9606         RSurf_DrawBatch();
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9610 {
9611         int i;
9612         float f;
9613         float alpha;
9614         const float *v;
9615         const float *n;
9616         float *c;
9617         vec3_t ambientcolor;
9618         vec3_t diffusecolor;
9619         vec3_t lightdir;
9620         // TODO: optimize
9621         // model lighting
9622         VectorCopy(rsurface.modellight_lightdir, lightdir);
9623         f = 0.5f * r_refdef.lightmapintensity;
9624         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9625         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9626         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9627         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9628         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9629         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9630         alpha = *a;
9631         if (VectorLength2(diffusecolor) > 0)
9632         {
9633                 // q3-style directional shading
9634                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9635                 rsurface.passcolor4f_vertexbuffer = 0;
9636                 rsurface.passcolor4f_bufferoffset = 0;
9637                 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)
9638                 {
9639                         if ((f = DotProduct(n, lightdir)) > 0)
9640                                 VectorMA(ambientcolor, f, diffusecolor, c);
9641                         else
9642                                 VectorCopy(ambientcolor, c);
9643                         c[3] = alpha;
9644                 }
9645                 *r = 1;
9646                 *g = 1;
9647                 *b = 1;
9648                 *a = 1;
9649                 *applycolor = false;
9650         }
9651         else
9652         {
9653                 *r = ambientcolor[0];
9654                 *g = ambientcolor[1];
9655                 *b = ambientcolor[2];
9656                 rsurface.passcolor4f = NULL;
9657                 rsurface.passcolor4f_vertexbuffer = 0;
9658                 rsurface.passcolor4f_bufferoffset = 0;
9659         }
9660 }
9661
9662 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9663 {
9664         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9665         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9666         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9667         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9668         GL_Color(r, g, b, a);
9669         RSurf_DrawBatch();
9670 }
9671
9672 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9673 {
9674         int i;
9675         float f;
9676         const float *v;
9677         float *c;
9678
9679         // fake shading
9680         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9681         rsurface.passcolor4f_vertexbuffer = 0;
9682         rsurface.passcolor4f_bufferoffset = 0;
9683
9684         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9685         {
9686                 f = 1 - RSurf_FogVertex(v);
9687                 c[0] = r;
9688                 c[1] = g;
9689                 c[2] = b;
9690                 c[3] = f * a;
9691         }
9692 }
9693
9694 void RSurf_SetupDepthAndCulling(void)
9695 {
9696         // submodels are biased to avoid z-fighting with world surfaces that they
9697         // may be exactly overlapping (avoids z-fighting artifacts on certain
9698         // doors and things in Quake maps)
9699         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9700         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9701         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9702         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9703 }
9704
9705 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9706 {
9707         // transparent sky would be ridiculous
9708         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9709                 return;
9710         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9711         skyrenderlater = true;
9712         RSurf_SetupDepthAndCulling();
9713         GL_DepthMask(true);
9714         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9715         // skymasking on them, and Quake3 never did sky masking (unlike
9716         // software Quake and software Quake2), so disable the sky masking
9717         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9718         // and skymasking also looks very bad when noclipping outside the
9719         // level, so don't use it then either.
9720         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9721         {
9722                 R_Mesh_ResetTextureState();
9723                 if (skyrendermasked)
9724                 {
9725                         R_SetupShader_DepthOrShadow(false);
9726                         // depth-only (masking)
9727                         GL_ColorMask(0,0,0,0);
9728                         // just to make sure that braindead drivers don't draw
9729                         // anything despite that colormask...
9730                         GL_BlendFunc(GL_ZERO, GL_ONE);
9731                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9732                         if (rsurface.batchvertex3fbuffer)
9733                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9734                         else
9735                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9736                 }
9737                 else
9738                 {
9739                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9740                         // fog sky
9741                         GL_BlendFunc(GL_ONE, GL_ZERO);
9742                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9743                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9744                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9745                 }
9746                 RSurf_DrawBatch();
9747                 if (skyrendermasked)
9748                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9749         }
9750         R_Mesh_ResetTextureState();
9751         GL_Color(1, 1, 1, 1);
9752 }
9753
9754 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9755 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9756 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9757 {
9758         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9759                 return;
9760         if (prepass)
9761         {
9762                 // render screenspace normalmap to texture
9763                 GL_DepthMask(true);
9764                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9765                 RSurf_DrawBatch();
9766         }
9767
9768         // bind lightmap texture
9769
9770         // water/refraction/reflection/camera surfaces have to be handled specially
9771         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9772         {
9773                 int start, end, startplaneindex;
9774                 for (start = 0;start < texturenumsurfaces;start = end)
9775                 {
9776                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9777                         if(startplaneindex < 0)
9778                         {
9779                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9780                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9781                                 end = start + 1;
9782                                 continue;
9783                         }
9784                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9785                                 ;
9786                         // now that we have a batch using the same planeindex, render it
9787                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9788                         {
9789                                 // render water or distortion background
9790                                 GL_DepthMask(true);
9791                                 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);
9792                                 RSurf_DrawBatch();
9793                                 // blend surface on top
9794                                 GL_DepthMask(false);
9795                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9796                                 RSurf_DrawBatch();
9797                         }
9798                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9799                         {
9800                                 // render surface with reflection texture as input
9801                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9802                                 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);
9803                                 RSurf_DrawBatch();
9804                         }
9805                 }
9806                 return;
9807         }
9808
9809         // render surface batch normally
9810         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9811         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);
9812         RSurf_DrawBatch();
9813 }
9814
9815 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9816 {
9817         // OpenGL 1.3 path - anything not completely ancient
9818         qboolean applycolor;
9819         qboolean applyfog;
9820         int layerindex;
9821         const texturelayer_t *layer;
9822         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);
9823         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9824
9825         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9826         {
9827                 vec4_t layercolor;
9828                 int layertexrgbscale;
9829                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9830                 {
9831                         if (layerindex == 0)
9832                                 GL_AlphaTest(true);
9833                         else
9834                         {
9835                                 GL_AlphaTest(false);
9836                                 GL_DepthFunc(GL_EQUAL);
9837                         }
9838                 }
9839                 GL_DepthMask(layer->depthmask && writedepth);
9840                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9841                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9842                 {
9843                         layertexrgbscale = 4;
9844                         VectorScale(layer->color, 0.25f, layercolor);
9845                 }
9846                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9847                 {
9848                         layertexrgbscale = 2;
9849                         VectorScale(layer->color, 0.5f, layercolor);
9850                 }
9851                 else
9852                 {
9853                         layertexrgbscale = 1;
9854                         VectorScale(layer->color, 1.0f, layercolor);
9855                 }
9856                 layercolor[3] = layer->color[3];
9857                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9858                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9859                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9860                 switch (layer->type)
9861                 {
9862                 case TEXTURELAYERTYPE_LITTEXTURE:
9863                         // single-pass lightmapped texture with 2x rgbscale
9864                         R_Mesh_TexBind(0, r_texture_white);
9865                         R_Mesh_TexMatrix(0, NULL);
9866                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9867                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9868                         R_Mesh_TexBind(1, layer->texture);
9869                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9870                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9871                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9872                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9873                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9874                         else if (FAKELIGHT_ENABLED)
9875                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9876                         else if (rsurface.uselightmaptexture)
9877                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9878                         else
9879                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9880                         break;
9881                 case TEXTURELAYERTYPE_TEXTURE:
9882                         // singletexture unlit texture with transparency support
9883                         R_Mesh_TexBind(0, layer->texture);
9884                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9885                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9886                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9887                         R_Mesh_TexBind(1, 0);
9888                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9889                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9890                         break;
9891                 case TEXTURELAYERTYPE_FOG:
9892                         // singletexture fogging
9893                         if (layer->texture)
9894                         {
9895                                 R_Mesh_TexBind(0, layer->texture);
9896                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9897                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9898                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9899                         }
9900                         else
9901                         {
9902                                 R_Mesh_TexBind(0, 0);
9903                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9904                         }
9905                         R_Mesh_TexBind(1, 0);
9906                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9907                         // generate a color array for the fog pass
9908                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9909                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9910                         RSurf_DrawBatch();
9911                         break;
9912                 default:
9913                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9914                 }
9915         }
9916         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9917         {
9918                 GL_DepthFunc(GL_LEQUAL);
9919                 GL_AlphaTest(false);
9920         }
9921 }
9922
9923 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9924 {
9925         // OpenGL 1.1 - crusty old voodoo path
9926         qboolean applyfog;
9927         int layerindex;
9928         const texturelayer_t *layer;
9929         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);
9930         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9931
9932         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9933         {
9934                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9935                 {
9936                         if (layerindex == 0)
9937                                 GL_AlphaTest(true);
9938                         else
9939                         {
9940                                 GL_AlphaTest(false);
9941                                 GL_DepthFunc(GL_EQUAL);
9942                         }
9943                 }
9944                 GL_DepthMask(layer->depthmask && writedepth);
9945                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9946                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9947                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9948                 switch (layer->type)
9949                 {
9950                 case TEXTURELAYERTYPE_LITTEXTURE:
9951                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9952                         {
9953                                 // two-pass lit texture with 2x rgbscale
9954                                 // first the lightmap pass
9955                                 R_Mesh_TexBind(0, r_texture_white);
9956                                 R_Mesh_TexMatrix(0, NULL);
9957                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9958                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9959                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9960                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9961                                 else if (FAKELIGHT_ENABLED)
9962                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9963                                 else if (rsurface.uselightmaptexture)
9964                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9965                                 else
9966                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9967                                 // then apply the texture to it
9968                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9969                                 R_Mesh_TexBind(0, layer->texture);
9970                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9971                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9972                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9973                                 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);
9974                         }
9975                         else
9976                         {
9977                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9978                                 R_Mesh_TexBind(0, layer->texture);
9979                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9980                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9981                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9982                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9983                                         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);
9984                                 else
9985                                         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);
9986                         }
9987                         break;
9988                 case TEXTURELAYERTYPE_TEXTURE:
9989                         // singletexture unlit texture with transparency support
9990                         R_Mesh_TexBind(0, layer->texture);
9991                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9992                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9993                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9994                         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);
9995                         break;
9996                 case TEXTURELAYERTYPE_FOG:
9997                         // singletexture fogging
9998                         if (layer->texture)
9999                         {
10000                                 R_Mesh_TexBind(0, layer->texture);
10001                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10002                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10003                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10004                         }
10005                         else
10006                         {
10007                                 R_Mesh_TexBind(0, 0);
10008                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10009                         }
10010                         // generate a color array for the fog pass
10011                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10012                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10013                         RSurf_DrawBatch();
10014                         break;
10015                 default:
10016                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10017                 }
10018         }
10019         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10020         {
10021                 GL_DepthFunc(GL_LEQUAL);
10022                 GL_AlphaTest(false);
10023         }
10024 }
10025
10026 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10027 {
10028         int vi;
10029         int j;
10030         r_vertexgeneric_t *batchvertex;
10031         float c[4];
10032
10033 //      R_Mesh_ResetTextureState();
10034         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10035
10036         if(rsurface.texture && rsurface.texture->currentskinframe)
10037         {
10038                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10039                 c[3] *= rsurface.texture->currentalpha;
10040         }
10041         else
10042         {
10043                 c[0] = 1;
10044                 c[1] = 0;
10045                 c[2] = 1;
10046                 c[3] = 1;
10047         }
10048
10049         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10050         {
10051                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10052                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10053                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10054         }
10055
10056         // brighten it up (as texture value 127 means "unlit")
10057         c[0] *= 2 * r_refdef.view.colorscale;
10058         c[1] *= 2 * r_refdef.view.colorscale;
10059         c[2] *= 2 * r_refdef.view.colorscale;
10060
10061         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10062                 c[3] *= r_wateralpha.value;
10063
10064         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10065         {
10066                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10067                 GL_DepthMask(false);
10068         }
10069         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10070         {
10071                 GL_BlendFunc(GL_ONE, GL_ONE);
10072                 GL_DepthMask(false);
10073         }
10074         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10075         {
10076                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10077                 GL_DepthMask(false);
10078         }
10079         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10080         {
10081                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10082                 GL_DepthMask(false);
10083         }
10084         else
10085         {
10086                 GL_BlendFunc(GL_ONE, GL_ZERO);
10087                 GL_DepthMask(writedepth);
10088         }
10089
10090         if (r_showsurfaces.integer == 3)
10091         {
10092                 rsurface.passcolor4f = NULL;
10093
10094                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10095                 {
10096                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10097
10098                         rsurface.passcolor4f = NULL;
10099                         rsurface.passcolor4f_vertexbuffer = 0;
10100                         rsurface.passcolor4f_bufferoffset = 0;
10101                 }
10102                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10103                 {
10104                         qboolean applycolor = true;
10105                         float one = 1.0;
10106
10107                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10108
10109                         r_refdef.lightmapintensity = 1;
10110                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10111                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10112                 }
10113                 else if (FAKELIGHT_ENABLED)
10114                 {
10115                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10116
10117                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10118                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10119                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10120                 }
10121                 else
10122                 {
10123                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10124
10125                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10126                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10127                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10128                 }
10129
10130                 if(!rsurface.passcolor4f)
10131                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10132
10133                 RSurf_DrawBatch_GL11_ApplyAmbient();
10134                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10135                 if(r_refdef.fogenabled)
10136                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10137                 RSurf_DrawBatch_GL11_ClampColor();
10138
10139                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10140                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10141                 RSurf_DrawBatch();
10142         }
10143         else if (!r_refdef.view.showdebug)
10144         {
10145                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10146                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10147                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10148                 {
10149                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10150                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10151                 }
10152                 R_Mesh_PrepareVertices_Generic_Unlock();
10153                 RSurf_DrawBatch();
10154         }
10155         else if (r_showsurfaces.integer == 4)
10156         {
10157                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10158                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10159                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10160                 {
10161                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10162                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10163                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10164                 }
10165                 R_Mesh_PrepareVertices_Generic_Unlock();
10166                 RSurf_DrawBatch();
10167         }
10168         else if (r_showsurfaces.integer == 2)
10169         {
10170                 const int *e;
10171                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10173                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10174                 {
10175                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10176                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10177                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10178                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10179                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10180                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10181                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10182                 }
10183                 R_Mesh_PrepareVertices_Generic_Unlock();
10184                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10185         }
10186         else
10187         {
10188                 int texturesurfaceindex;
10189                 int k;
10190                 const msurface_t *surface;
10191                 float surfacecolor4f[4];
10192                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10193                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10194                 vi = 0;
10195                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10196                 {
10197                         surface = texturesurfacelist[texturesurfaceindex];
10198                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10199                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10200                         for (j = 0;j < surface->num_vertices;j++)
10201                         {
10202                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10203                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10204                                 vi++;
10205                         }
10206                 }
10207                 R_Mesh_PrepareVertices_Generic_Unlock();
10208                 RSurf_DrawBatch();
10209         }
10210 }
10211
10212 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10213 {
10214         CHECKGLERROR
10215         RSurf_SetupDepthAndCulling();
10216         if (r_showsurfaces.integer)
10217         {
10218                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10219                 return;
10220         }
10221         switch (vid.renderpath)
10222         {
10223         case RENDERPATH_GL20:
10224         case RENDERPATH_D3D9:
10225         case RENDERPATH_D3D10:
10226         case RENDERPATH_D3D11:
10227         case RENDERPATH_SOFT:
10228         case RENDERPATH_GLES2:
10229                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10230                 break;
10231         case RENDERPATH_GL13:
10232         case RENDERPATH_GLES1:
10233                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10234                 break;
10235         case RENDERPATH_GL11:
10236                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10237                 break;
10238         }
10239         CHECKGLERROR
10240 }
10241
10242 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10243 {
10244         CHECKGLERROR
10245         RSurf_SetupDepthAndCulling();
10246         if (r_showsurfaces.integer)
10247         {
10248                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10249                 return;
10250         }
10251         switch (vid.renderpath)
10252         {
10253         case RENDERPATH_GL20:
10254         case RENDERPATH_D3D9:
10255         case RENDERPATH_D3D10:
10256         case RENDERPATH_D3D11:
10257         case RENDERPATH_SOFT:
10258         case RENDERPATH_GLES2:
10259                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10260                 break;
10261         case RENDERPATH_GL13:
10262         case RENDERPATH_GLES1:
10263                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10264                 break;
10265         case RENDERPATH_GL11:
10266                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10267                 break;
10268         }
10269         CHECKGLERROR
10270 }
10271
10272 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10273 {
10274         int i, j;
10275         int texturenumsurfaces, endsurface;
10276         texture_t *texture;
10277         const msurface_t *surface;
10278         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10279
10280         // if the model is static it doesn't matter what value we give for
10281         // wantnormals and wanttangents, so this logic uses only rules applicable
10282         // to a model, knowing that they are meaningless otherwise
10283         if (ent == r_refdef.scene.worldentity)
10284                 RSurf_ActiveWorldEntity();
10285         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10286                 RSurf_ActiveModelEntity(ent, false, false, false);
10287         else
10288         {
10289                 switch (vid.renderpath)
10290                 {
10291                 case RENDERPATH_GL20:
10292                 case RENDERPATH_D3D9:
10293                 case RENDERPATH_D3D10:
10294                 case RENDERPATH_D3D11:
10295                 case RENDERPATH_SOFT:
10296                 case RENDERPATH_GLES2:
10297                         RSurf_ActiveModelEntity(ent, true, true, false);
10298                         break;
10299                 case RENDERPATH_GL11:
10300                 case RENDERPATH_GL13:
10301                 case RENDERPATH_GLES1:
10302                         RSurf_ActiveModelEntity(ent, true, false, false);
10303                         break;
10304                 }
10305         }
10306
10307         if (r_transparentdepthmasking.integer)
10308         {
10309                 qboolean setup = false;
10310                 for (i = 0;i < numsurfaces;i = j)
10311                 {
10312                         j = i + 1;
10313                         surface = rsurface.modelsurfaces + surfacelist[i];
10314                         texture = surface->texture;
10315                         rsurface.texture = R_GetCurrentTexture(texture);
10316                         rsurface.lightmaptexture = NULL;
10317                         rsurface.deluxemaptexture = NULL;
10318                         rsurface.uselightmaptexture = false;
10319                         // scan ahead until we find a different texture
10320                         endsurface = min(i + 1024, numsurfaces);
10321                         texturenumsurfaces = 0;
10322                         texturesurfacelist[texturenumsurfaces++] = surface;
10323                         for (;j < endsurface;j++)
10324                         {
10325                                 surface = rsurface.modelsurfaces + surfacelist[j];
10326                                 if (texture != surface->texture)
10327                                         break;
10328                                 texturesurfacelist[texturenumsurfaces++] = surface;
10329                         }
10330                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10331                                 continue;
10332                         // render the range of surfaces as depth
10333                         if (!setup)
10334                         {
10335                                 setup = true;
10336                                 GL_ColorMask(0,0,0,0);
10337                                 GL_Color(1,1,1,1);
10338                                 GL_DepthTest(true);
10339                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10340                                 GL_DepthMask(true);
10341 //                              R_Mesh_ResetTextureState();
10342                                 R_SetupShader_DepthOrShadow(false);
10343                         }
10344                         RSurf_SetupDepthAndCulling();
10345                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10346                         if (rsurface.batchvertex3fbuffer)
10347                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10348                         else
10349                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10350                         RSurf_DrawBatch();
10351                 }
10352                 if (setup)
10353                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10354         }
10355
10356         for (i = 0;i < numsurfaces;i = j)
10357         {
10358                 j = i + 1;
10359                 surface = rsurface.modelsurfaces + surfacelist[i];
10360                 texture = surface->texture;
10361                 rsurface.texture = R_GetCurrentTexture(texture);
10362                 // scan ahead until we find a different texture
10363                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10364                 texturenumsurfaces = 0;
10365                 texturesurfacelist[texturenumsurfaces++] = surface;
10366                 if(FAKELIGHT_ENABLED)
10367                 {
10368                         rsurface.lightmaptexture = NULL;
10369                         rsurface.deluxemaptexture = NULL;
10370                         rsurface.uselightmaptexture = false;
10371                         for (;j < endsurface;j++)
10372                         {
10373                                 surface = rsurface.modelsurfaces + surfacelist[j];
10374                                 if (texture != surface->texture)
10375                                         break;
10376                                 texturesurfacelist[texturenumsurfaces++] = surface;
10377                         }
10378                 }
10379                 else
10380                 {
10381                         rsurface.lightmaptexture = surface->lightmaptexture;
10382                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10383                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10384                         for (;j < endsurface;j++)
10385                         {
10386                                 surface = rsurface.modelsurfaces + surfacelist[j];
10387                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10388                                         break;
10389                                 texturesurfacelist[texturenumsurfaces++] = surface;
10390                         }
10391                 }
10392                 // render the range of surfaces
10393                 if (ent == r_refdef.scene.worldentity)
10394                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10395                 else
10396                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10397         }
10398         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10399 }
10400
10401 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10402 {
10403         // transparent surfaces get pushed off into the transparent queue
10404         int surfacelistindex;
10405         const msurface_t *surface;
10406         vec3_t tempcenter, center;
10407         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10408         {
10409                 surface = texturesurfacelist[surfacelistindex];
10410                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10411                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10412                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10413                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10414                 if (queueentity->transparent_offset) // transparent offset
10415                 {
10416                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10417                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10418                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10419                 }
10420                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10421         }
10422 }
10423
10424 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10425 {
10426         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10427                 return;
10428         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10429                 return;
10430         RSurf_SetupDepthAndCulling();
10431         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10432         if (rsurface.batchvertex3fbuffer)
10433                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10434         else
10435                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10436         RSurf_DrawBatch();
10437 }
10438
10439 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10440 {
10441         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10442         CHECKGLERROR
10443         if (depthonly)
10444                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10445         else if (prepass)
10446         {
10447                 if (!rsurface.texture->currentnumlayers)
10448                         return;
10449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10450                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10451                 else
10452                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10453         }
10454         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10455                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10456         else if (!rsurface.texture->currentnumlayers)
10457                 return;
10458         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10459         {
10460                 // in the deferred case, transparent surfaces were queued during prepass
10461                 if (!r_shadow_usingdeferredprepass)
10462                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10463         }
10464         else
10465         {
10466                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10467                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10468         }
10469         CHECKGLERROR
10470 }
10471
10472 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10473 {
10474         int i, j;
10475         texture_t *texture;
10476         R_FrameData_SetMark();
10477         // break the surface list down into batches by texture and use of lightmapping
10478         for (i = 0;i < numsurfaces;i = j)
10479         {
10480                 j = i + 1;
10481                 // texture is the base texture pointer, rsurface.texture is the
10482                 // current frame/skin the texture is directing us to use (for example
10483                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10484                 // use skin 1 instead)
10485                 texture = surfacelist[i]->texture;
10486                 rsurface.texture = R_GetCurrentTexture(texture);
10487                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10488                 {
10489                         // if this texture is not the kind we want, skip ahead to the next one
10490                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10491                                 ;
10492                         continue;
10493                 }
10494                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10495                 {
10496                         rsurface.lightmaptexture = NULL;
10497                         rsurface.deluxemaptexture = NULL;
10498                         rsurface.uselightmaptexture = false;
10499                         // simply scan ahead until we find a different texture or lightmap state
10500                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10501                                 ;
10502                 }
10503                 else
10504                 {
10505                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10506                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10507                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10508                         // simply scan ahead until we find a different texture or lightmap state
10509                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10510                                 ;
10511                 }
10512                 // render the range of surfaces
10513                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10514         }
10515         R_FrameData_ReturnToMark();
10516 }
10517
10518 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10519 {
10520         CHECKGLERROR
10521         if (depthonly)
10522                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10523         else if (prepass)
10524         {
10525                 if (!rsurface.texture->currentnumlayers)
10526                         return;
10527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10528                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10529                 else
10530                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10531         }
10532         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10533                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10534         else if (!rsurface.texture->currentnumlayers)
10535                 return;
10536         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10537         {
10538                 // in the deferred case, transparent surfaces were queued during prepass
10539                 if (!r_shadow_usingdeferredprepass)
10540                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10541         }
10542         else
10543         {
10544                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10545                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10546         }
10547         CHECKGLERROR
10548 }
10549
10550 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10551 {
10552         int i, j;
10553         texture_t *texture;
10554         R_FrameData_SetMark();
10555         // break the surface list down into batches by texture and use of lightmapping
10556         for (i = 0;i < numsurfaces;i = j)
10557         {
10558                 j = i + 1;
10559                 // texture is the base texture pointer, rsurface.texture is the
10560                 // current frame/skin the texture is directing us to use (for example
10561                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10562                 // use skin 1 instead)
10563                 texture = surfacelist[i]->texture;
10564                 rsurface.texture = R_GetCurrentTexture(texture);
10565                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10566                 {
10567                         // if this texture is not the kind we want, skip ahead to the next one
10568                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10569                                 ;
10570                         continue;
10571                 }
10572                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10573                 {
10574                         rsurface.lightmaptexture = NULL;
10575                         rsurface.deluxemaptexture = NULL;
10576                         rsurface.uselightmaptexture = false;
10577                         // simply scan ahead until we find a different texture or lightmap state
10578                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10579                                 ;
10580                 }
10581                 else
10582                 {
10583                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10584                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10585                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10586                         // simply scan ahead until we find a different texture or lightmap state
10587                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10588                                 ;
10589                 }
10590                 // render the range of surfaces
10591                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10592         }
10593         R_FrameData_ReturnToMark();
10594 }
10595
10596 float locboxvertex3f[6*4*3] =
10597 {
10598         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10599         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10600         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10601         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10602         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10603         1,0,0, 0,0,0, 0,1,0, 1,1,0
10604 };
10605
10606 unsigned short locboxelements[6*2*3] =
10607 {
10608          0, 1, 2, 0, 2, 3,
10609          4, 5, 6, 4, 6, 7,
10610          8, 9,10, 8,10,11,
10611         12,13,14, 12,14,15,
10612         16,17,18, 16,18,19,
10613         20,21,22, 20,22,23
10614 };
10615
10616 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10617 {
10618         int i, j;
10619         cl_locnode_t *loc = (cl_locnode_t *)ent;
10620         vec3_t mins, size;
10621         float vertex3f[6*4*3];
10622         CHECKGLERROR
10623         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10624         GL_DepthMask(false);
10625         GL_DepthRange(0, 1);
10626         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10627         GL_DepthTest(true);
10628         GL_CullFace(GL_NONE);
10629         R_EntityMatrix(&identitymatrix);
10630
10631 //      R_Mesh_ResetTextureState();
10632
10633         i = surfacelist[0];
10634         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10635                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10636                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10637                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10638
10639         if (VectorCompare(loc->mins, loc->maxs))
10640         {
10641                 VectorSet(size, 2, 2, 2);
10642                 VectorMA(loc->mins, -0.5f, size, mins);
10643         }
10644         else
10645         {
10646                 VectorCopy(loc->mins, mins);
10647                 VectorSubtract(loc->maxs, loc->mins, size);
10648         }
10649
10650         for (i = 0;i < 6*4*3;)
10651                 for (j = 0;j < 3;j++, i++)
10652                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10653
10654         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10655         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10656         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10657 }
10658
10659 void R_DrawLocs(void)
10660 {
10661         int index;
10662         cl_locnode_t *loc, *nearestloc;
10663         vec3_t center;
10664         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10665         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10666         {
10667                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10668                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10669         }
10670 }
10671
10672 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10673 {
10674         if (decalsystem->decals)
10675                 Mem_Free(decalsystem->decals);
10676         memset(decalsystem, 0, sizeof(*decalsystem));
10677 }
10678
10679 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)
10680 {
10681         tridecal_t *decal;
10682         tridecal_t *decals;
10683         int i;
10684
10685         // expand or initialize the system
10686         if (decalsystem->maxdecals <= decalsystem->numdecals)
10687         {
10688                 decalsystem_t old = *decalsystem;
10689                 qboolean useshortelements;
10690                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10691                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10692                 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)));
10693                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10694                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10695                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10696                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10697                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10698                 if (decalsystem->numdecals)
10699                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10700                 if (old.decals)
10701                         Mem_Free(old.decals);
10702                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10703                         decalsystem->element3i[i] = i;
10704                 if (useshortelements)
10705                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10706                                 decalsystem->element3s[i] = i;
10707         }
10708
10709         // grab a decal and search for another free slot for the next one
10710         decals = decalsystem->decals;
10711         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10712         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10713                 ;
10714         decalsystem->freedecal = i;
10715         if (decalsystem->numdecals <= i)
10716                 decalsystem->numdecals = i + 1;
10717
10718         // initialize the decal
10719         decal->lived = 0;
10720         decal->triangleindex = triangleindex;
10721         decal->surfaceindex = surfaceindex;
10722         decal->decalsequence = decalsequence;
10723         decal->color4f[0][0] = c0[0];
10724         decal->color4f[0][1] = c0[1];
10725         decal->color4f[0][2] = c0[2];
10726         decal->color4f[0][3] = 1;
10727         decal->color4f[1][0] = c1[0];
10728         decal->color4f[1][1] = c1[1];
10729         decal->color4f[1][2] = c1[2];
10730         decal->color4f[1][3] = 1;
10731         decal->color4f[2][0] = c2[0];
10732         decal->color4f[2][1] = c2[1];
10733         decal->color4f[2][2] = c2[2];
10734         decal->color4f[2][3] = 1;
10735         decal->vertex3f[0][0] = v0[0];
10736         decal->vertex3f[0][1] = v0[1];
10737         decal->vertex3f[0][2] = v0[2];
10738         decal->vertex3f[1][0] = v1[0];
10739         decal->vertex3f[1][1] = v1[1];
10740         decal->vertex3f[1][2] = v1[2];
10741         decal->vertex3f[2][0] = v2[0];
10742         decal->vertex3f[2][1] = v2[1];
10743         decal->vertex3f[2][2] = v2[2];
10744         decal->texcoord2f[0][0] = t0[0];
10745         decal->texcoord2f[0][1] = t0[1];
10746         decal->texcoord2f[1][0] = t1[0];
10747         decal->texcoord2f[1][1] = t1[1];
10748         decal->texcoord2f[2][0] = t2[0];
10749         decal->texcoord2f[2][1] = t2[1];
10750         TriangleNormal(v0, v1, v2, decal->plane);
10751         VectorNormalize(decal->plane);
10752         decal->plane[3] = DotProduct(v0, decal->plane);
10753 }
10754
10755 extern cvar_t cl_decals_bias;
10756 extern cvar_t cl_decals_models;
10757 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10758 // baseparms, parms, temps
10759 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)
10760 {
10761         int cornerindex;
10762         int index;
10763         float v[9][3];
10764         const float *vertex3f;
10765         const float *normal3f;
10766         int numpoints;
10767         float points[2][9][3];
10768         float temp[3];
10769         float tc[9][2];
10770         float f;
10771         float c[9][4];
10772         const int *e;
10773
10774         e = rsurface.modelelement3i + 3*triangleindex;
10775
10776         vertex3f = rsurface.modelvertex3f;
10777         normal3f = rsurface.modelnormal3f;
10778
10779         if (normal3f)
10780         {
10781                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10782                 {
10783                         index = 3*e[cornerindex];
10784                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10785                 }
10786         }
10787         else
10788         {
10789                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10790                 {
10791                         index = 3*e[cornerindex];
10792                         VectorCopy(vertex3f + index, v[cornerindex]);
10793                 }
10794         }
10795
10796         // cull backfaces
10797         //TriangleNormal(v[0], v[1], v[2], normal);
10798         //if (DotProduct(normal, localnormal) < 0.0f)
10799         //      continue;
10800         // clip by each of the box planes formed from the projection matrix
10801         // if anything survives, we emit the decal
10802         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]);
10803         if (numpoints < 3)
10804                 return;
10805         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]);
10806         if (numpoints < 3)
10807                 return;
10808         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]);
10809         if (numpoints < 3)
10810                 return;
10811         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]);
10812         if (numpoints < 3)
10813                 return;
10814         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]);
10815         if (numpoints < 3)
10816                 return;
10817         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]);
10818         if (numpoints < 3)
10819                 return;
10820         // some part of the triangle survived, so we have to accept it...
10821         if (dynamic)
10822         {
10823                 // dynamic always uses the original triangle
10824                 numpoints = 3;
10825                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10826                 {
10827                         index = 3*e[cornerindex];
10828                         VectorCopy(vertex3f + index, v[cornerindex]);
10829                 }
10830         }
10831         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10832         {
10833                 // convert vertex positions to texcoords
10834                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10835                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10836                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10837                 // calculate distance fade from the projection origin
10838                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10839                 f = bound(0.0f, f, 1.0f);
10840                 c[cornerindex][0] = r * f;
10841                 c[cornerindex][1] = g * f;
10842                 c[cornerindex][2] = b * f;
10843                 c[cornerindex][3] = 1.0f;
10844                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10845         }
10846         if (dynamic)
10847                 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);
10848         else
10849                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10850                         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);
10851 }
10852 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)
10853 {
10854         matrix4x4_t projection;
10855         decalsystem_t *decalsystem;
10856         qboolean dynamic;
10857         dp_model_t *model;
10858         const msurface_t *surface;
10859         const msurface_t *surfaces;
10860         const int *surfacelist;
10861         const texture_t *texture;
10862         int numtriangles;
10863         int numsurfacelist;
10864         int surfacelistindex;
10865         int surfaceindex;
10866         int triangleindex;
10867         float localorigin[3];
10868         float localnormal[3];
10869         float localmins[3];
10870         float localmaxs[3];
10871         float localsize;
10872         //float normal[3];
10873         float planes[6][4];
10874         float angles[3];
10875         bih_t *bih;
10876         int bih_triangles_count;
10877         int bih_triangles[256];
10878         int bih_surfaces[256];
10879
10880         decalsystem = &ent->decalsystem;
10881         model = ent->model;
10882         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10883         {
10884                 R_DecalSystem_Reset(&ent->decalsystem);
10885                 return;
10886         }
10887
10888         if (!model->brush.data_leafs && !cl_decals_models.integer)
10889         {
10890                 if (decalsystem->model)
10891                         R_DecalSystem_Reset(decalsystem);
10892                 return;
10893         }
10894
10895         if (decalsystem->model != model)
10896                 R_DecalSystem_Reset(decalsystem);
10897         decalsystem->model = model;
10898
10899         RSurf_ActiveModelEntity(ent, true, false, false);
10900
10901         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10902         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10903         VectorNormalize(localnormal);
10904         localsize = worldsize*rsurface.inversematrixscale;
10905         localmins[0] = localorigin[0] - localsize;
10906         localmins[1] = localorigin[1] - localsize;
10907         localmins[2] = localorigin[2] - localsize;
10908         localmaxs[0] = localorigin[0] + localsize;
10909         localmaxs[1] = localorigin[1] + localsize;
10910         localmaxs[2] = localorigin[2] + localsize;
10911
10912         //VectorCopy(localnormal, planes[4]);
10913         //VectorVectors(planes[4], planes[2], planes[0]);
10914         AnglesFromVectors(angles, localnormal, NULL, false);
10915         AngleVectors(angles, planes[0], planes[2], planes[4]);
10916         VectorNegate(planes[0], planes[1]);
10917         VectorNegate(planes[2], planes[3]);
10918         VectorNegate(planes[4], planes[5]);
10919         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10920         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10921         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10922         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10923         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10924         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10925
10926 #if 1
10927 // works
10928 {
10929         matrix4x4_t forwardprojection;
10930         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10931         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10932 }
10933 #else
10934 // broken
10935 {
10936         float projectionvector[4][3];
10937         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10938         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10939         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10940         projectionvector[0][0] = planes[0][0] * ilocalsize;
10941         projectionvector[0][1] = planes[1][0] * ilocalsize;
10942         projectionvector[0][2] = planes[2][0] * ilocalsize;
10943         projectionvector[1][0] = planes[0][1] * ilocalsize;
10944         projectionvector[1][1] = planes[1][1] * ilocalsize;
10945         projectionvector[1][2] = planes[2][1] * ilocalsize;
10946         projectionvector[2][0] = planes[0][2] * ilocalsize;
10947         projectionvector[2][1] = planes[1][2] * ilocalsize;
10948         projectionvector[2][2] = planes[2][2] * ilocalsize;
10949         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10950         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10951         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10952         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10953 }
10954 #endif
10955
10956         dynamic = model->surfmesh.isanimated;
10957         numsurfacelist = model->nummodelsurfaces;
10958         surfacelist = model->sortedmodelsurfaces;
10959         surfaces = model->data_surfaces;
10960
10961         bih = NULL;
10962         bih_triangles_count = -1;
10963         if(!dynamic)
10964         {
10965                 if(model->render_bih.numleafs)
10966                         bih = &model->render_bih;
10967                 else if(model->collision_bih.numleafs)
10968                         bih = &model->collision_bih;
10969         }
10970         if(bih)
10971                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10972         if(bih_triangles_count == 0)
10973                 return;
10974         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10975                 return;
10976         if(bih_triangles_count > 0)
10977         {
10978                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10979                 {
10980                         surfaceindex = bih_surfaces[triangleindex];
10981                         surface = surfaces + surfaceindex;
10982                         texture = surface->texture;
10983                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10984                                 continue;
10985                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10986                                 continue;
10987                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10988                 }
10989         }
10990         else
10991         {
10992                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10993                 {
10994                         surfaceindex = surfacelist[surfacelistindex];
10995                         surface = surfaces + surfaceindex;
10996                         // check cull box first because it rejects more than any other check
10997                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10998                                 continue;
10999                         // skip transparent surfaces
11000                         texture = surface->texture;
11001                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11002                                 continue;
11003                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11004                                 continue;
11005                         numtriangles = surface->num_triangles;
11006                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11007                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11008                 }
11009         }
11010 }
11011
11012 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11013 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)
11014 {
11015         int renderentityindex;
11016         float worldmins[3];
11017         float worldmaxs[3];
11018         entity_render_t *ent;
11019
11020         if (!cl_decals_newsystem.integer)
11021                 return;
11022
11023         worldmins[0] = worldorigin[0] - worldsize;
11024         worldmins[1] = worldorigin[1] - worldsize;
11025         worldmins[2] = worldorigin[2] - worldsize;
11026         worldmaxs[0] = worldorigin[0] + worldsize;
11027         worldmaxs[1] = worldorigin[1] + worldsize;
11028         worldmaxs[2] = worldorigin[2] + worldsize;
11029
11030         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11031
11032         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11033         {
11034                 ent = r_refdef.scene.entities[renderentityindex];
11035                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11036                         continue;
11037
11038                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11039         }
11040 }
11041
11042 typedef struct r_decalsystem_splatqueue_s
11043 {
11044         vec3_t worldorigin;
11045         vec3_t worldnormal;
11046         float color[4];
11047         float tcrange[4];
11048         float worldsize;
11049         int decalsequence;
11050 }
11051 r_decalsystem_splatqueue_t;
11052
11053 int r_decalsystem_numqueued = 0;
11054 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11055
11056 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)
11057 {
11058         r_decalsystem_splatqueue_t *queue;
11059
11060         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11061                 return;
11062
11063         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11064         VectorCopy(worldorigin, queue->worldorigin);
11065         VectorCopy(worldnormal, queue->worldnormal);
11066         Vector4Set(queue->color, r, g, b, a);
11067         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11068         queue->worldsize = worldsize;
11069         queue->decalsequence = cl.decalsequence++;
11070 }
11071
11072 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11073 {
11074         int i;
11075         r_decalsystem_splatqueue_t *queue;
11076
11077         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11078                 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);
11079         r_decalsystem_numqueued = 0;
11080 }
11081
11082 extern cvar_t cl_decals_max;
11083 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11084 {
11085         int i;
11086         decalsystem_t *decalsystem = &ent->decalsystem;
11087         int numdecals;
11088         int killsequence;
11089         tridecal_t *decal;
11090         float frametime;
11091         float lifetime;
11092
11093         if (!decalsystem->numdecals)
11094                 return;
11095
11096         if (r_showsurfaces.integer)
11097                 return;
11098
11099         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11100         {
11101                 R_DecalSystem_Reset(decalsystem);
11102                 return;
11103         }
11104
11105         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11106         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11107
11108         if (decalsystem->lastupdatetime)
11109                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11110         else
11111                 frametime = 0;
11112         decalsystem->lastupdatetime = r_refdef.scene.time;
11113         decal = decalsystem->decals;
11114         numdecals = decalsystem->numdecals;
11115
11116         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11117         {
11118                 if (decal->color4f[0][3])
11119                 {
11120                         decal->lived += frametime;
11121                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11122                         {
11123                                 memset(decal, 0, sizeof(*decal));
11124                                 if (decalsystem->freedecal > i)
11125                                         decalsystem->freedecal = i;
11126                         }
11127                 }
11128         }
11129         decal = decalsystem->decals;
11130         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11131                 numdecals--;
11132
11133         // collapse the array by shuffling the tail decals into the gaps
11134         for (;;)
11135         {
11136                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11137                         decalsystem->freedecal++;
11138                 if (decalsystem->freedecal == numdecals)
11139                         break;
11140                 decal[decalsystem->freedecal] = decal[--numdecals];
11141         }
11142
11143         decalsystem->numdecals = numdecals;
11144
11145         if (numdecals <= 0)
11146         {
11147                 // if there are no decals left, reset decalsystem
11148                 R_DecalSystem_Reset(decalsystem);
11149         }
11150 }
11151
11152 extern skinframe_t *decalskinframe;
11153 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11154 {
11155         int i;
11156         decalsystem_t *decalsystem = &ent->decalsystem;
11157         int numdecals;
11158         tridecal_t *decal;
11159         float faderate;
11160         float alpha;
11161         float *v3f;
11162         float *c4f;
11163         float *t2f;
11164         const int *e;
11165         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11166         int numtris = 0;
11167
11168         numdecals = decalsystem->numdecals;
11169         if (!numdecals)
11170                 return;
11171
11172         if (r_showsurfaces.integer)
11173                 return;
11174
11175         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11176         {
11177                 R_DecalSystem_Reset(decalsystem);
11178                 return;
11179         }
11180
11181         // if the model is static it doesn't matter what value we give for
11182         // wantnormals and wanttangents, so this logic uses only rules applicable
11183         // to a model, knowing that they are meaningless otherwise
11184         if (ent == r_refdef.scene.worldentity)
11185                 RSurf_ActiveWorldEntity();
11186         else
11187                 RSurf_ActiveModelEntity(ent, false, false, false);
11188
11189         decalsystem->lastupdatetime = r_refdef.scene.time;
11190         decal = decalsystem->decals;
11191
11192         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11193
11194         // update vertex positions for animated models
11195         v3f = decalsystem->vertex3f;
11196         c4f = decalsystem->color4f;
11197         t2f = decalsystem->texcoord2f;
11198         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11199         {
11200                 if (!decal->color4f[0][3])
11201                         continue;
11202
11203                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11204                         continue;
11205
11206                 // skip backfaces
11207                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11208                         continue;
11209
11210                 // update color values for fading decals
11211                 if (decal->lived >= cl_decals_time.value)
11212                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11213                 else
11214                         alpha = 1.0f;
11215
11216                 c4f[ 0] = decal->color4f[0][0] * alpha;
11217                 c4f[ 1] = decal->color4f[0][1] * alpha;
11218                 c4f[ 2] = decal->color4f[0][2] * alpha;
11219                 c4f[ 3] = 1;
11220                 c4f[ 4] = decal->color4f[1][0] * alpha;
11221                 c4f[ 5] = decal->color4f[1][1] * alpha;
11222                 c4f[ 6] = decal->color4f[1][2] * alpha;
11223                 c4f[ 7] = 1;
11224                 c4f[ 8] = decal->color4f[2][0] * alpha;
11225                 c4f[ 9] = decal->color4f[2][1] * alpha;
11226                 c4f[10] = decal->color4f[2][2] * alpha;
11227                 c4f[11] = 1;
11228
11229                 t2f[0] = decal->texcoord2f[0][0];
11230                 t2f[1] = decal->texcoord2f[0][1];
11231                 t2f[2] = decal->texcoord2f[1][0];
11232                 t2f[3] = decal->texcoord2f[1][1];
11233                 t2f[4] = decal->texcoord2f[2][0];
11234                 t2f[5] = decal->texcoord2f[2][1];
11235
11236                 // update vertex positions for animated models
11237                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11238                 {
11239                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11240                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11241                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11242                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11243                 }
11244                 else
11245                 {
11246                         VectorCopy(decal->vertex3f[0], v3f);
11247                         VectorCopy(decal->vertex3f[1], v3f + 3);
11248                         VectorCopy(decal->vertex3f[2], v3f + 6);
11249                 }
11250
11251                 if (r_refdef.fogenabled)
11252                 {
11253                         alpha = RSurf_FogVertex(v3f);
11254                         VectorScale(c4f, alpha, c4f);
11255                         alpha = RSurf_FogVertex(v3f + 3);
11256                         VectorScale(c4f + 4, alpha, c4f + 4);
11257                         alpha = RSurf_FogVertex(v3f + 6);
11258                         VectorScale(c4f + 8, alpha, c4f + 8);
11259                 }
11260
11261                 v3f += 9;
11262                 c4f += 12;
11263                 t2f += 6;
11264                 numtris++;
11265         }
11266
11267         if (numtris > 0)
11268         {
11269                 r_refdef.stats.drawndecals += numtris;
11270
11271                 // now render the decals all at once
11272                 // (this assumes they all use one particle font texture!)
11273                 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);
11274 //              R_Mesh_ResetTextureState();
11275                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11276                 GL_DepthMask(false);
11277                 GL_DepthRange(0, 1);
11278                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11279                 GL_DepthTest(true);
11280                 GL_CullFace(GL_NONE);
11281                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11282                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11283                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11284         }
11285 }
11286
11287 static void R_DrawModelDecals(void)
11288 {
11289         int i, numdecals;
11290
11291         // fade faster when there are too many decals
11292         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11293         for (i = 0;i < r_refdef.scene.numentities;i++)
11294                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11295
11296         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11297         for (i = 0;i < r_refdef.scene.numentities;i++)
11298                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11299                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11300
11301         R_DecalSystem_ApplySplatEntitiesQueue();
11302
11303         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11304         for (i = 0;i < r_refdef.scene.numentities;i++)
11305                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11306
11307         r_refdef.stats.totaldecals += numdecals;
11308
11309         if (r_showsurfaces.integer)
11310                 return;
11311
11312         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11313
11314         for (i = 0;i < r_refdef.scene.numentities;i++)
11315         {
11316                 if (!r_refdef.viewcache.entityvisible[i])
11317                         continue;
11318                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11319                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11320         }
11321 }
11322
11323 extern cvar_t mod_collision_bih;
11324 void R_DrawDebugModel(void)
11325 {
11326         entity_render_t *ent = rsurface.entity;
11327         int i, j, k, l, flagsmask;
11328         const msurface_t *surface;
11329         dp_model_t *model = ent->model;
11330         vec3_t v;
11331
11332         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11333                 return;
11334
11335         if (r_showoverdraw.value > 0)
11336         {
11337                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11338                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11339                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11340                 GL_DepthTest(false);
11341                 GL_DepthMask(false);
11342                 GL_DepthRange(0, 1);
11343                 GL_BlendFunc(GL_ONE, GL_ONE);
11344                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11345                 {
11346                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11347                                 continue;
11348                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11349                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11350                         {
11351                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11352                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11353                                 if (!rsurface.texture->currentlayers->depthmask)
11354                                         GL_Color(c, 0, 0, 1.0f);
11355                                 else if (ent == r_refdef.scene.worldentity)
11356                                         GL_Color(c, c, c, 1.0f);
11357                                 else
11358                                         GL_Color(0, c, 0, 1.0f);
11359                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11360                                 RSurf_DrawBatch();
11361                         }
11362                 }
11363                 rsurface.texture = NULL;
11364         }
11365
11366         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11367
11368 //      R_Mesh_ResetTextureState();
11369         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11370         GL_DepthRange(0, 1);
11371         GL_DepthTest(!r_showdisabledepthtest.integer);
11372         GL_DepthMask(false);
11373         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11374
11375         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11376         {
11377                 int triangleindex;
11378                 int bihleafindex;
11379                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11380                 const q3mbrush_t *brush;
11381                 const bih_t *bih = &model->collision_bih;
11382                 const bih_leaf_t *bihleaf;
11383                 float vertex3f[3][3];
11384                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11385                 cullbox = false;
11386                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11387                 {
11388                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11389                                 continue;
11390                         switch (bihleaf->type)
11391                         {
11392                         case BIH_BRUSH:
11393                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11394                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11395                                 {
11396                                         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);
11397                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11398                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11399                                 }
11400                                 break;
11401                         case BIH_COLLISIONTRIANGLE:
11402                                 triangleindex = bihleaf->itemindex;
11403                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11404                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11405                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11406                                 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);
11407                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11408                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11409                                 break;
11410                         case BIH_RENDERTRIANGLE:
11411                                 triangleindex = bihleaf->itemindex;
11412                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11413                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11414                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11415                                 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);
11416                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11417                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11418                                 break;
11419                         }
11420                 }
11421         }
11422
11423         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11424
11425 #ifndef USE_GLES2
11426         if (r_showtris.integer && qglPolygonMode)
11427         {
11428                 if (r_showdisabledepthtest.integer)
11429                 {
11430                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11431                         GL_DepthMask(false);
11432                 }
11433                 else
11434                 {
11435                         GL_BlendFunc(GL_ONE, GL_ZERO);
11436                         GL_DepthMask(true);
11437                 }
11438                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11439                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11440                 {
11441                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11442                                 continue;
11443                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11444                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11445                         {
11446                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11447                                 if (!rsurface.texture->currentlayers->depthmask)
11448                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11449                                 else if (ent == r_refdef.scene.worldentity)
11450                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11451                                 else
11452                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11453                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11454                                 RSurf_DrawBatch();
11455                         }
11456                 }
11457                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11458                 rsurface.texture = NULL;
11459         }
11460
11461         if (r_shownormals.value != 0 && qglBegin)
11462         {
11463                 if (r_showdisabledepthtest.integer)
11464                 {
11465                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11466                         GL_DepthMask(false);
11467                 }
11468                 else
11469                 {
11470                         GL_BlendFunc(GL_ONE, GL_ZERO);
11471                         GL_DepthMask(true);
11472                 }
11473                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11474                 {
11475                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11476                                 continue;
11477                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11478                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11479                         {
11480                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11481                                 qglBegin(GL_LINES);
11482                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11483                                 {
11484                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11485                                         {
11486                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11487                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11488                                                 qglVertex3f(v[0], v[1], v[2]);
11489                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11490                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11491                                                 qglVertex3f(v[0], v[1], v[2]);
11492                                         }
11493                                 }
11494                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11495                                 {
11496                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11497                                         {
11498                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11499                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11500                                                 qglVertex3f(v[0], v[1], v[2]);
11501                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11502                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11503                                                 qglVertex3f(v[0], v[1], v[2]);
11504                                         }
11505                                 }
11506                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11507                                 {
11508                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11509                                         {
11510                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11511                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11512                                                 qglVertex3f(v[0], v[1], v[2]);
11513                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11514                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11515                                                 qglVertex3f(v[0], v[1], v[2]);
11516                                         }
11517                                 }
11518                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11519                                 {
11520                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11521                                         {
11522                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11523                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11524                                                 qglVertex3f(v[0], v[1], v[2]);
11525                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11526                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11527                                                 qglVertex3f(v[0], v[1], v[2]);
11528                                         }
11529                                 }
11530                                 qglEnd();
11531                                 CHECKGLERROR
11532                         }
11533                 }
11534                 rsurface.texture = NULL;
11535         }
11536 #endif
11537 }
11538
11539 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11540 int r_maxsurfacelist = 0;
11541 const msurface_t **r_surfacelist = NULL;
11542 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11543 {
11544         int i, j, endj, flagsmask;
11545         dp_model_t *model = r_refdef.scene.worldmodel;
11546         msurface_t *surfaces;
11547         unsigned char *update;
11548         int numsurfacelist = 0;
11549         if (model == NULL)
11550                 return;
11551
11552         if (r_maxsurfacelist < model->num_surfaces)
11553         {
11554                 r_maxsurfacelist = model->num_surfaces;
11555                 if (r_surfacelist)
11556                         Mem_Free((msurface_t**)r_surfacelist);
11557                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11558         }
11559
11560         RSurf_ActiveWorldEntity();
11561
11562         surfaces = model->data_surfaces;
11563         update = model->brushq1.lightmapupdateflags;
11564
11565         // update light styles on this submodel
11566         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11567         {
11568                 model_brush_lightstyleinfo_t *style;
11569                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11570                 {
11571                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11572                         {
11573                                 int *list = style->surfacelist;
11574                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11575                                 for (j = 0;j < style->numsurfaces;j++)
11576                                         update[list[j]] = true;
11577                         }
11578                 }
11579         }
11580
11581         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11582
11583         if (debug)
11584         {
11585                 R_DrawDebugModel();
11586                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11587                 return;
11588         }
11589
11590         rsurface.lightmaptexture = NULL;
11591         rsurface.deluxemaptexture = NULL;
11592         rsurface.uselightmaptexture = false;
11593         rsurface.texture = NULL;
11594         rsurface.rtlight = NULL;
11595         numsurfacelist = 0;
11596         // add visible surfaces to draw list
11597         for (i = 0;i < model->nummodelsurfaces;i++)
11598         {
11599                 j = model->sortedmodelsurfaces[i];
11600                 if (r_refdef.viewcache.world_surfacevisible[j])
11601                         r_surfacelist[numsurfacelist++] = surfaces + j;
11602         }
11603         // update lightmaps if needed
11604         if (model->brushq1.firstrender)
11605         {
11606                 model->brushq1.firstrender = false;
11607                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11608                         if (update[j])
11609                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11610         }
11611         else if (update)
11612         {
11613                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11614                         if (r_refdef.viewcache.world_surfacevisible[j])
11615                                 if (update[j])
11616                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11617         }
11618         // don't do anything if there were no surfaces
11619         if (!numsurfacelist)
11620         {
11621                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11622                 return;
11623         }
11624         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11625
11626         // add to stats if desired
11627         if (r_speeds.integer && !skysurfaces && !depthonly)
11628         {
11629                 r_refdef.stats.world_surfaces += numsurfacelist;
11630                 for (j = 0;j < numsurfacelist;j++)
11631                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11632         }
11633
11634         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11635 }
11636
11637 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11638 {
11639         int i, j, endj, flagsmask;
11640         dp_model_t *model = ent->model;
11641         msurface_t *surfaces;
11642         unsigned char *update;
11643         int numsurfacelist = 0;
11644         if (model == NULL)
11645                 return;
11646
11647         if (r_maxsurfacelist < model->num_surfaces)
11648         {
11649                 r_maxsurfacelist = model->num_surfaces;
11650                 if (r_surfacelist)
11651                         Mem_Free((msurface_t **)r_surfacelist);
11652                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11653         }
11654
11655         // if the model is static it doesn't matter what value we give for
11656         // wantnormals and wanttangents, so this logic uses only rules applicable
11657         // to a model, knowing that they are meaningless otherwise
11658         if (ent == r_refdef.scene.worldentity)
11659                 RSurf_ActiveWorldEntity();
11660         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11661                 RSurf_ActiveModelEntity(ent, false, false, false);
11662         else if (prepass)
11663                 RSurf_ActiveModelEntity(ent, true, true, true);
11664         else if (depthonly)
11665         {
11666                 switch (vid.renderpath)
11667                 {
11668                 case RENDERPATH_GL20:
11669                 case RENDERPATH_D3D9:
11670                 case RENDERPATH_D3D10:
11671                 case RENDERPATH_D3D11:
11672                 case RENDERPATH_SOFT:
11673                 case RENDERPATH_GLES2:
11674                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11675                         break;
11676                 case RENDERPATH_GL11:
11677                 case RENDERPATH_GL13:
11678                 case RENDERPATH_GLES1:
11679                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11680                         break;
11681                 }
11682         }
11683         else
11684         {
11685                 switch (vid.renderpath)
11686                 {
11687                 case RENDERPATH_GL20:
11688                 case RENDERPATH_D3D9:
11689                 case RENDERPATH_D3D10:
11690                 case RENDERPATH_D3D11:
11691                 case RENDERPATH_SOFT:
11692                 case RENDERPATH_GLES2:
11693                         RSurf_ActiveModelEntity(ent, true, true, false);
11694                         break;
11695                 case RENDERPATH_GL11:
11696                 case RENDERPATH_GL13:
11697                 case RENDERPATH_GLES1:
11698                         RSurf_ActiveModelEntity(ent, true, false, false);
11699                         break;
11700                 }
11701         }
11702
11703         surfaces = model->data_surfaces;
11704         update = model->brushq1.lightmapupdateflags;
11705
11706         // update light styles
11707         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11708         {
11709                 model_brush_lightstyleinfo_t *style;
11710                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11711                 {
11712                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11713                         {
11714                                 int *list = style->surfacelist;
11715                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11716                                 for (j = 0;j < style->numsurfaces;j++)
11717                                         update[list[j]] = true;
11718                         }
11719                 }
11720         }
11721
11722         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11723
11724         if (debug)
11725         {
11726                 R_DrawDebugModel();
11727                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11728                 return;
11729         }
11730
11731         rsurface.lightmaptexture = NULL;
11732         rsurface.deluxemaptexture = NULL;
11733         rsurface.uselightmaptexture = false;
11734         rsurface.texture = NULL;
11735         rsurface.rtlight = NULL;
11736         numsurfacelist = 0;
11737         // add visible surfaces to draw list
11738         for (i = 0;i < model->nummodelsurfaces;i++)
11739                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11740         // don't do anything if there were no surfaces
11741         if (!numsurfacelist)
11742         {
11743                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11744                 return;
11745         }
11746         // update lightmaps if needed
11747         if (update)
11748         {
11749                 int updated = 0;
11750                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11751                 {
11752                         if (update[j])
11753                         {
11754                                 updated++;
11755                                 R_BuildLightMap(ent, surfaces + j);
11756                         }
11757                 }
11758         }
11759         if (update)
11760                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11761                         if (update[j])
11762                                 R_BuildLightMap(ent, surfaces + j);
11763         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11764
11765         // add to stats if desired
11766         if (r_speeds.integer && !skysurfaces && !depthonly)
11767         {
11768                 r_refdef.stats.entities_surfaces += numsurfacelist;
11769                 for (j = 0;j < numsurfacelist;j++)
11770                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11771         }
11772
11773         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11774 }
11775
11776 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11777 {
11778         static texture_t texture;
11779         static msurface_t surface;
11780         const msurface_t *surfacelist = &surface;
11781
11782         // fake enough texture and surface state to render this geometry
11783
11784         texture.update_lastrenderframe = -1; // regenerate this texture
11785         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11786         texture.currentskinframe = skinframe;
11787         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11788         texture.offsetmapping = OFFSETMAPPING_OFF;
11789         texture.offsetscale = 1;
11790         texture.specularscalemod = 1;
11791         texture.specularpowermod = 1;
11792
11793         surface.texture = &texture;
11794         surface.num_triangles = numtriangles;
11795         surface.num_firsttriangle = firsttriangle;
11796         surface.num_vertices = numvertices;
11797         surface.num_firstvertex = firstvertex;
11798
11799         // now render it
11800         rsurface.texture = R_GetCurrentTexture(surface.texture);
11801         rsurface.lightmaptexture = NULL;
11802         rsurface.deluxemaptexture = NULL;
11803         rsurface.uselightmaptexture = false;
11804         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11805 }
11806
11807 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)
11808 {
11809         static msurface_t surface;
11810         const msurface_t *surfacelist = &surface;
11811
11812         // fake enough texture and surface state to render this geometry
11813         surface.texture = texture;
11814         surface.num_triangles = numtriangles;
11815         surface.num_firsttriangle = firsttriangle;
11816         surface.num_vertices = numvertices;
11817         surface.num_firstvertex = firstvertex;
11818
11819         // now render it
11820         rsurface.texture = R_GetCurrentTexture(surface.texture);
11821         rsurface.lightmaptexture = NULL;
11822         rsurface.deluxemaptexture = NULL;
11823         rsurface.uselightmaptexture = false;
11824         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11825 }