]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
overhauling a lot of functions to allow fbo rendering
[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 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
186
187 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
188 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
189 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
190 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
191
192 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
193 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
194 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
195 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
196 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
197 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
198 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
199
200 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
201 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
202 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
203 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)"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 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"};
214
215 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"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 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"};
223
224 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."};
225
226 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)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1456         qboolean debugshader = gl_paranoid.integer != 0;
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (!debugshader)
1460         {
1461                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1462                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1463         }
1464         if ((!vsbin && vertstring) || (!psbin && fragstring))
1465         {
1466                 const char* dllnames_d3dx9 [] =
1467                 {
1468                         "d3dx9_43.dll",
1469                         "d3dx9_42.dll",
1470                         "d3dx9_41.dll",
1471                         "d3dx9_40.dll",
1472                         "d3dx9_39.dll",
1473                         "d3dx9_38.dll",
1474                         "d3dx9_37.dll",
1475                         "d3dx9_36.dll",
1476                         "d3dx9_35.dll",
1477                         "d3dx9_34.dll",
1478                         "d3dx9_33.dll",
1479                         "d3dx9_32.dll",
1480                         "d3dx9_31.dll",
1481                         "d3dx9_30.dll",
1482                         "d3dx9_29.dll",
1483                         "d3dx9_28.dll",
1484                         "d3dx9_27.dll",
1485                         "d3dx9_26.dll",
1486                         "d3dx9_25.dll",
1487                         "d3dx9_24.dll",
1488                         NULL
1489                 };
1490                 dllhandle_t d3dx9_dll = NULL;
1491                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1493                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 dllfunction_t d3dx9_dllfuncs[] =
1495                 {
1496                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1497                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1498                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1499                         {NULL, NULL}
1500                 };
1501                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1502                 {
1503                         DWORD shaderflags = 0;
1504                         if (debugshader)
1505                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1506                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1507                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1508                         if (vertstring && vertstring[0])
1509                         {
1510                                 if (debugshader)
1511                                 {
1512 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1513 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1514                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1515                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1516                                 }
1517                                 else
1518                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 if (vsbuffer)
1520                                 {
1521                                         vsbinsize = vsbuffer->GetBufferSize();
1522                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1523                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1524                                         vsbuffer->Release();
1525                                 }
1526                                 if (vslog)
1527                                 {
1528                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1529                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1530                                         vslog->Release();
1531                                 }
1532                         }
1533                         if (fragstring && fragstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1538 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1539                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1540                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1541                                 }
1542                                 else
1543                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 if (psbuffer)
1545                                 {
1546                                         psbinsize = psbuffer->GetBufferSize();
1547                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1548                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1549                                         psbuffer->Release();
1550                                 }
1551                                 if (pslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         pslog->Release();
1556                                 }
1557                         }
1558                         Sys_UnloadLibrary(&d3dx9_dll);
1559                 }
1560                 else
1561                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1562         }
1563         if (vsbin && psbin)
1564         {
1565                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1566                 if (FAILED(vsresult))
1567                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1568                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1569                 if (FAILED(psresult))
1570                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1571         }
1572         // free the shader data
1573         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1574         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1575 }
1576
1577 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1578 {
1579         int i;
1580         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1581         int vertstring_length = 0;
1582         int geomstring_length = 0;
1583         int fragstring_length = 0;
1584         char *t;
1585         char *vertexstring, *geometrystring, *fragmentstring;
1586         char *vertstring, *geomstring, *fragstring;
1587         char permutationname[256];
1588         char cachename[256];
1589         int vertstrings_count = 0;
1590         int geomstrings_count = 0;
1591         int fragstrings_count = 0;
1592         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595
1596         if (p->compiled)
1597                 return;
1598         p->compiled = true;
1599         p->vertexshader = NULL;
1600         p->pixelshader = NULL;
1601
1602         permutationname[0] = 0;
1603         cachename[0] = 0;
1604         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1605         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1606         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1607
1608         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1609         strlcat(cachename, "hlsl/", sizeof(cachename));
1610
1611         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1612         vertstrings_count = 0;
1613         geomstrings_count = 0;
1614         fragstrings_count = 0;
1615         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1616         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1617         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1618
1619         // the first pretext is which type of shader to compile as
1620         // (later these will all be bound together as a program object)
1621         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1622         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1623         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1624
1625         // the second pretext is the mode (for example a light source)
1626         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1627         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1628         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1629         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1630         strlcat(cachename, modeinfo->name, sizeof(cachename));
1631
1632         // now add all the permutation pretexts
1633         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1634         {
1635                 if (permutation & (1<<i))
1636                 {
1637                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1642                 }
1643                 else
1644                 {
1645                         // keep line numbers correct
1646                         vertstrings_list[vertstrings_count++] = "\n";
1647                         geomstrings_list[geomstrings_count++] = "\n";
1648                         fragstrings_list[fragstrings_count++] = "\n";
1649                 }
1650         }
1651
1652         // add static parms
1653         R_CompileShader_AddStaticParms(mode, permutation);
1654         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         vertstrings_count += shaderstaticparms_count;
1656         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         geomstrings_count += shaderstaticparms_count;
1658         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         fragstrings_count += shaderstaticparms_count;
1660
1661         // replace spaces in the cachename with _ characters
1662         for (i = 0;cachename[i];i++)
1663                 if (cachename[i] == ' ')
1664                         cachename[i] = '_';
1665
1666         // now append the shader text itself
1667         vertstrings_list[vertstrings_count++] = vertexstring;
1668         geomstrings_list[geomstrings_count++] = geometrystring;
1669         fragstrings_list[fragstrings_count++] = fragmentstring;
1670
1671         // if any sources were NULL, clear the respective list
1672         if (!vertexstring)
1673                 vertstrings_count = 0;
1674         if (!geometrystring)
1675                 geomstrings_count = 0;
1676         if (!fragmentstring)
1677                 fragstrings_count = 0;
1678
1679         vertstring_length = 0;
1680         for (i = 0;i < vertstrings_count;i++)
1681                 vertstring_length += strlen(vertstrings_list[i]);
1682         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1683         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1684                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1685
1686         geomstring_length = 0;
1687         for (i = 0;i < geomstrings_count;i++)
1688                 geomstring_length += strlen(geomstrings_list[i]);
1689         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1690         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1691                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1692
1693         fragstring_length = 0;
1694         for (i = 0;i < fragstrings_count;i++)
1695                 fragstring_length += strlen(fragstrings_list[i]);
1696         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1697         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1698                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1699
1700         // try to load the cached shader, or generate one
1701         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1702
1703         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1704                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1705         else
1706                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1707
1708         // free the strings
1709         if (vertstring)
1710                 Mem_Free(vertstring);
1711         if (geomstring)
1712                 Mem_Free(geomstring);
1713         if (fragstring)
1714                 Mem_Free(fragstring);
1715         if (vertexstring)
1716                 Mem_Free(vertexstring);
1717         if (geometrystring)
1718                 Mem_Free(geometrystring);
1719         if (fragmentstring)
1720                 Mem_Free(fragmentstring);
1721 }
1722
1723 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1724 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1725 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);}
1726 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);}
1727 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);}
1728 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);}
1729
1730 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1731 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1732 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);}
1733 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);}
1734 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);}
1735 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);}
1736
1737 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1738 {
1739         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1740         if (r_hlsl_permutation != perm)
1741         {
1742                 r_hlsl_permutation = perm;
1743                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1744                 {
1745                         if (!r_hlsl_permutation->compiled)
1746                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                         {
1749                                 // remove features until we find a valid permutation
1750                                 int i;
1751                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1752                                 {
1753                                         // reduce i more quickly whenever it would not remove any bits
1754                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1755                                         if (!(permutation & j))
1756                                                 continue;
1757                                         permutation -= j;
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         if (!r_hlsl_permutation->compiled)
1760                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1762                                                 break;
1763                                 }
1764                                 if (i >= SHADERPERMUTATION_COUNT)
1765                                 {
1766                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         return; // no bit left to clear, entire mode is broken
1769                                 }
1770                         }
1771                 }
1772                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1773                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1774         }
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1777         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1778 }
1779 #endif
1780
1781 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1782 {
1783         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1786         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1787 }
1788
1789 void R_GLSL_Restart_f(void)
1790 {
1791         unsigned int i, limit;
1792         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1793                 Mem_Free(glslshaderstring);
1794         glslshaderstring = NULL;
1795         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1796                 Mem_Free(hlslshaderstring);
1797         hlslshaderstring = NULL;
1798         switch(vid.renderpath)
1799         {
1800         case RENDERPATH_D3D9:
1801 #ifdef SUPPORTD3D
1802                 {
1803                         r_hlsl_permutation_t *p;
1804                         r_hlsl_permutation = NULL;
1805                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1806                         for (i = 0;i < limit;i++)
1807                         {
1808                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1809                                 {
1810                                         if (p->vertexshader)
1811                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1812                                         if (p->pixelshader)
1813                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1814                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1815                                 }
1816                         }
1817                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1818                 }
1819 #endif
1820                 break;
1821         case RENDERPATH_D3D10:
1822                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1823                 break;
1824         case RENDERPATH_D3D11:
1825                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_GL20:
1828         case RENDERPATH_GLES2:
1829                 {
1830                         r_glsl_permutation_t *p;
1831                         r_glsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1836                                 {
1837                                         GL_Backend_FreeProgram(p->program);
1838                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1842                 }
1843                 break;
1844         case RENDERPATH_GL11:
1845         case RENDERPATH_GL13:
1846         case RENDERPATH_GLES1:
1847                 break;
1848         case RENDERPATH_SOFT:
1849                 break;
1850         }
1851 }
1852
1853 void R_GLSL_DumpShader_f(void)
1854 {
1855         int i;
1856         qfile_t *file;
1857
1858         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1859         if (file)
1860         {
1861                 FS_Print(file, "/* The engine may define the following macros:\n");
1862                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1863                 for (i = 0;i < SHADERMODE_COUNT;i++)
1864                         FS_Print(file, glslshadermodeinfo[i].pretext);
1865                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1866                         FS_Print(file, shaderpermutationinfo[i].pretext);
1867                 FS_Print(file, "*/\n");
1868                 FS_Print(file, builtinshaderstring);
1869                 FS_Close(file);
1870                 Con_Printf("glsl/default.glsl written\n");
1871         }
1872         else
1873                 Con_Printf("failed to write to glsl/default.glsl\n");
1874
1875         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1876         if (file)
1877         {
1878                 FS_Print(file, "/* The engine may define the following macros:\n");
1879                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1880                 for (i = 0;i < SHADERMODE_COUNT;i++)
1881                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1882                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                         FS_Print(file, shaderpermutationinfo[i].pretext);
1884                 FS_Print(file, "*/\n");
1885                 FS_Print(file, builtinhlslshaderstring);
1886                 FS_Close(file);
1887                 Con_Printf("hlsl/default.hlsl written\n");
1888         }
1889         else
1890                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1891 }
1892
1893 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1894 {
1895         unsigned int permutation = 0;
1896         if (r_trippy.integer && !notrippy)
1897                 permutation |= SHADERPERMUTATION_TRIPPY;
1898         permutation |= SHADERPERMUTATION_VIEWTINT;
1899         if (first)
1900                 permutation |= SHADERPERMUTATION_DIFFUSE;
1901         if (second)
1902                 permutation |= SHADERPERMUTATION_SPECULAR;
1903         if (texturemode == GL_MODULATE)
1904                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1905         else if (texturemode == GL_ADD)
1906                 permutation |= SHADERPERMUTATION_GLOW;
1907         else if (texturemode == GL_DECAL)
1908                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1909         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1910                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1911         if (!second)
1912                 texturemode = GL_MODULATE;
1913         if (vid.allowalphatocoverage)
1914                 GL_AlphaToCoverage(false);
1915         switch (vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1920                 R_Mesh_TexBind(GL20TU_FIRST , first );
1921                 R_Mesh_TexBind(GL20TU_SECOND, second);
1922                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1923                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1938                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1939                 break;
1940         case RENDERPATH_GL13:
1941         case RENDERPATH_GLES1:
1942                 R_Mesh_TexBind(0, first );
1943                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1944                 R_Mesh_TexBind(1, second);
1945                 if (second)
1946                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1947                 break;
1948         case RENDERPATH_GL11:
1949                 R_Mesh_TexBind(0, first );
1950                 break;
1951         case RENDERPATH_SOFT:
1952                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 break;
1956         }
1957 }
1958
1959 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1960 {
1961         unsigned int permutation = 0;
1962         if (r_trippy.integer && !notrippy)
1963                 permutation |= SHADERPERMUTATION_TRIPPY;
1964         if (vid.allowalphatocoverage)
1965                 GL_AlphaToCoverage(false);
1966         switch (vid.renderpath)
1967         {
1968         case RENDERPATH_D3D9:
1969 #ifdef SUPPORTD3D
1970                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1971 #endif
1972                 break;
1973         case RENDERPATH_D3D10:
1974                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1975                 break;
1976         case RENDERPATH_D3D11:
1977                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1978                 break;
1979         case RENDERPATH_GL20:
1980         case RENDERPATH_GLES2:
1981                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1982                 break;
1983         case RENDERPATH_GL13:
1984         case RENDERPATH_GLES1:
1985                 R_Mesh_TexBind(0, 0);
1986                 R_Mesh_TexBind(1, 0);
1987                 break;
1988         case RENDERPATH_GL11:
1989                 R_Mesh_TexBind(0, 0);
1990                 break;
1991         case RENDERPATH_SOFT:
1992                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1993                 break;
1994         }
1995 }
1996
1997 void R_SetupShader_ShowDepth(qboolean notrippy)
1998 {
1999         int permutation = 0;
2000         if (r_trippy.integer && !notrippy)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (vid.allowalphatocoverage)
2003                 GL_AlphaToCoverage(false);
2004         switch (vid.renderpath)
2005         {
2006         case RENDERPATH_D3D9:
2007 #ifdef SUPPORTHLSL
2008                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2009 #endif
2010                 break;
2011         case RENDERPATH_D3D10:
2012                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_D3D11:
2015                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016                 break;
2017         case RENDERPATH_GL20:
2018         case RENDERPATH_GLES2:
2019                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2020                 break;
2021         case RENDERPATH_GL13:
2022         case RENDERPATH_GLES1:
2023                 break;
2024         case RENDERPATH_GL11:
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         }
2030 }
2031
2032 extern qboolean r_shadow_usingdeferredprepass;
2033 extern cvar_t r_shadow_deferred_8bitrange;
2034 extern rtexture_t *r_shadow_attenuationgradienttexture;
2035 extern rtexture_t *r_shadow_attenuation2dtexture;
2036 extern rtexture_t *r_shadow_attenuation3dtexture;
2037 extern qboolean r_shadow_usingshadowmap2d;
2038 extern qboolean r_shadow_usingshadowmaportho;
2039 extern float r_shadow_shadowmap_texturescale[2];
2040 extern float r_shadow_shadowmap_parameters[4];
2041 extern qboolean r_shadow_shadowmapvsdct;
2042 extern qboolean r_shadow_shadowmapsampler;
2043 extern int r_shadow_shadowmappcf;
2044 extern rtexture_t *r_shadow_shadowmap2dtexture;
2045 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2046 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2047 extern matrix4x4_t r_shadow_shadowmapmatrix;
2048 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2049 extern int r_shadow_prepass_width;
2050 extern int r_shadow_prepass_height;
2051 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2052 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2054 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2055 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2056
2057 #define BLENDFUNC_ALLOWS_COLORMOD      1
2058 #define BLENDFUNC_ALLOWS_FOG           2
2059 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2060 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2061 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2062 static int R_BlendFuncFlags(int src, int dst)
2063 {
2064         int r = 0;
2065
2066         // a blendfunc allows colormod if:
2067         // a) it can never keep the destination pixel invariant, or
2068         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2069         // this is to prevent unintended side effects from colormod
2070
2071         // a blendfunc allows fog if:
2072         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2073         // this is to prevent unintended side effects from fog
2074
2075         // these checks are the output of fogeval.pl
2076
2077         r |= BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2087         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099
2100         return r;
2101 }
2102
2103 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)
2104 {
2105         // select a permutation of the lighting shader appropriate to this
2106         // combination of texture, entity, light source, and fogging, only use the
2107         // minimum features necessary to avoid wasting rendering time in the
2108         // fragment shader on features that are not being used
2109         unsigned int permutation = 0;
2110         unsigned int mode = 0;
2111         int blendfuncflags;
2112         static float dummy_colormod[3] = {1, 1, 1};
2113         float *colormod = rsurface.colormod;
2114         float m16f[16];
2115         matrix4x4_t tempmatrix;
2116         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2117         if (r_trippy.integer && !notrippy)
2118                 permutation |= SHADERPERMUTATION_TRIPPY;
2119         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2120                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2121         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2122                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2123         if (rsurfacepass == RSURFPASS_BACKGROUND)
2124         {
2125                 // distorted background
2126                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127                 {
2128                         mode = SHADERMODE_WATER;
2129                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2130                         {
2131                                 // this is the right thing to do for wateralpha
2132                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2133                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                         }
2135                         else
2136                         {
2137                                 // this is the right thing to do for entity alpha
2138                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2140                         }
2141                 }
2142                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2143                 {
2144                         mode = SHADERMODE_REFRACTION;
2145                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                 }
2148                 else
2149                 {
2150                         mode = SHADERMODE_GENERIC;
2151                         permutation |= SHADERPERMUTATION_DIFFUSE;
2152                         GL_BlendFunc(GL_ONE, GL_ZERO);
2153                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154                 }
2155                 if (vid.allowalphatocoverage)
2156                         GL_AlphaToCoverage(false);
2157         }
2158         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2159         {
2160                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2161                 {
2162                         switch(rsurface.texture->offsetmapping)
2163                         {
2164                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2165                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2167                         case OFFSETMAPPING_OFF: break;
2168                         }
2169                 }
2170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2171                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172                 // normalmap (deferred prepass), may use alpha test on diffuse
2173                 mode = SHADERMODE_DEFERREDGEOMETRY;
2174                 GL_BlendFunc(GL_ONE, GL_ZERO);
2175                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2176                 if (vid.allowalphatocoverage)
2177                         GL_AlphaToCoverage(false);
2178         }
2179         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2180         {
2181                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2182                 {
2183                         switch(rsurface.texture->offsetmapping)
2184                         {
2185                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2186                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2188                         case OFFSETMAPPING_OFF: break;
2189                         }
2190                 }
2191                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193                 // light source
2194                 mode = SHADERMODE_LIGHTSOURCE;
2195                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2196                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2197                 if (diffusescale > 0)
2198                         permutation |= SHADERPERMUTATION_DIFFUSE;
2199                 if (specularscale > 0)
2200                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2201                 if (r_refdef.fogenabled)
2202                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2203                 if (rsurface.texture->colormapping)
2204                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2205                 if (r_shadow_usingshadowmap2d)
2206                 {
2207                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2208                         if(r_shadow_shadowmapvsdct)
2209                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2210
2211                         if (r_shadow_shadowmapsampler)
2212                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2213                         if (r_shadow_shadowmappcf > 1)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2215                         else if (r_shadow_shadowmappcf)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2217                 }
2218                 if (rsurface.texture->reflectmasktexture)
2219                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2220                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2221                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2222                 if (vid.allowalphatocoverage)
2223                         GL_AlphaToCoverage(false);
2224         }
2225         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2226         {
2227                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2228                 {
2229                         switch(rsurface.texture->offsetmapping)
2230                         {
2231                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2232                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2234                         case OFFSETMAPPING_OFF: break;
2235                         }
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239                 // unshaded geometry (fullbright or ambient model lighting)
2240                 mode = SHADERMODE_FLATCOLOR;
2241                 ambientscale = diffusescale = specularscale = 0;
2242                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2243                         permutation |= SHADERPERMUTATION_GLOW;
2244                 if (r_refdef.fogenabled)
2245                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2246                 if (rsurface.texture->colormapping)
2247                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2248                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2249                 {
2250                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2251                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2252
2253                         if (r_shadow_shadowmapsampler)
2254                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2255                         if (r_shadow_shadowmappcf > 1)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2257                         else if (r_shadow_shadowmappcf)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2259                 }
2260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2261                         permutation |= SHADERPERMUTATION_REFLECTION;
2262                 if (rsurface.texture->reflectmasktexture)
2263                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266                 // when using alphatocoverage, we don't need alphakill
2267                 if (vid.allowalphatocoverage)
2268                 {
2269                         if (r_transparent_alphatocoverage.integer)
2270                         {
2271                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2272                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2273                         }
2274                         else
2275                                 GL_AlphaToCoverage(false);
2276                 }
2277         }
2278         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2279         {
2280                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 // directional model lighting
2293                 mode = SHADERMODE_LIGHTDIRECTION;
2294                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2295                         permutation |= SHADERPERMUTATION_GLOW;
2296                 permutation |= SHADERPERMUTATION_DIFFUSE;
2297                 if (specularscale > 0)
2298                         permutation |= SHADERPERMUTATION_SPECULAR;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329                 // when using alphatocoverage, we don't need alphakill
2330                 if (vid.allowalphatocoverage)
2331                 {
2332                         if (r_transparent_alphatocoverage.integer)
2333                         {
2334                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2335                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2336                         }
2337                         else
2338                                 GL_AlphaToCoverage(false);
2339                 }
2340         }
2341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2344                 {
2345                         switch(rsurface.texture->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 // ambient model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 // lightmapped wall
2416                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2417                         permutation |= SHADERPERMUTATION_GLOW;
2418                 if (r_refdef.fogenabled)
2419                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2420                 if (rsurface.texture->colormapping)
2421                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2422                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2423                 {
2424                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2425                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2426
2427                         if (r_shadow_shadowmapsampler)
2428                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2429                         if (r_shadow_shadowmappcf > 1)
2430                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2431                         else if (r_shadow_shadowmappcf)
2432                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2433                 }
2434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (rsurface.texture->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (specularscale > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (specularscale > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         if (rsurface.uselightmaptexture)
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2464                         else
2465                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2466                         permutation |= SHADERPERMUTATION_DIFFUSE;
2467                         if (specularscale > 0)
2468                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2469                 }
2470                 else if (rsurface.uselightmaptexture)
2471                 {
2472                         // ordinary lightmapping (q1bsp, q3bsp)
2473                         mode = SHADERMODE_LIGHTMAP;
2474                 }
2475                 else
2476                 {
2477                         // ordinary vertex coloring (q3bsp)
2478                         mode = SHADERMODE_VERTEXCOLOR;
2479                 }
2480                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2481                 {
2482                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2483                         if (r_shadow_bouncegriddirectional)
2484                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2485                 }
2486                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2488                 // when using alphatocoverage, we don't need alphakill
2489                 if (vid.allowalphatocoverage)
2490                 {
2491                         if (r_transparent_alphatocoverage.integer)
2492                         {
2493                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2494                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2495                         }
2496                         else
2497                                 GL_AlphaToCoverage(false);
2498                 }
2499         }
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2501                 colormod = dummy_colormod;
2502         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2503                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2504         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2505                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2506         switch(vid.renderpath)
2507         {
2508         case RENDERPATH_D3D9:
2509 #ifdef SUPPORTD3D
2510                 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);
2511                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2512                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2513                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2514                 if (mode == SHADERMODE_LIGHTSOURCE)
2515                 {
2516                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2517                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2518                 }
2519                 else
2520                 {
2521                         if (mode == SHADERMODE_LIGHTDIRECTION)
2522                         {
2523                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2524                         }
2525                 }
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2528                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2529                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2530                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2531
2532                 if (mode == SHADERMODE_LIGHTSOURCE)
2533                 {
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2538                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2539
2540                         // additive passes are only darkened by fog, not tinted
2541                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2542                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2543                 }
2544                 else
2545                 {
2546                         if (mode == SHADERMODE_FLATCOLOR)
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2549                         }
2550                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2551                         {
2552                                 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]);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2554                                 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);
2555                                 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);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2559                         }
2560                         else
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2564                                 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);
2565                                 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);
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2567                         }
2568                         // additive passes are only darkened by fog, not tinted
2569                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571                         else
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2573                         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);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2580                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2581                         if (mode == SHADERMODE_WATER)
2582                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2583                 }
2584                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2585                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2586                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2587                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2588                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2589                 if (rsurface.texture->pantstexture)
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2591                 else
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2593                 if (rsurface.texture->shirttexture)
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2595                 else
2596                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2597                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2601                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2602                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2603                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2605                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2606                         );
2607                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2608                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2610                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2611
2612                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2613                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2614                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2615                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2621                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2623                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2624                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2625                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2626                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2627                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2628                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2629                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2630                 {
2631                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2632                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2633                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2634                 }
2635                 else
2636                 {
2637                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2638                 }
2639 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2640 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2641                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2642                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2643                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2644                 {
2645                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2646                         if (rsurface.rtlight)
2647                         {
2648                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2649                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2650                         }
2651                 }
2652 #endif
2653                 break;
2654         case RENDERPATH_D3D10:
2655                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656                 break;
2657         case RENDERPATH_D3D11:
2658                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659                 break;
2660         case RENDERPATH_GL20:
2661         case RENDERPATH_GLES2:
2662                 if (!vid.useinterleavedarrays)
2663                 {
2664                         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);
2665                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2666                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2672                 }
2673                 else
2674                 {
2675                         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);
2676                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2677                 }
2678                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2679                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2680                 if (mode == SHADERMODE_LIGHTSOURCE)
2681                 {
2682                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2683                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2684                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2685                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2686                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2687                         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);
2688         
2689                         // additive passes are only darkened by fog, not tinted
2690                         if (r_glsl_permutation->loc_FogColor >= 0)
2691                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2692                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2693                 }
2694                 else
2695                 {
2696                         if (mode == SHADERMODE_FLATCOLOR)
2697                         {
2698                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2699                         }
2700                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2701                         {
2702                                 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]);
2703                                 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]);
2704                                 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);
2705                                 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);
2706                                 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);
2707                                 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]);
2708                                 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]);
2709                         }
2710                         else
2711                         {
2712                                 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]);
2713                                 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]);
2714                                 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);
2715                                 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);
2716                                 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);
2717                         }
2718                         // additive passes are only darkened by fog, not tinted
2719                         if (r_glsl_permutation->loc_FogColor >= 0)
2720                         {
2721                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2722                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2723                                 else
2724                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2725                         }
2726                         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);
2727                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2728                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2729                         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]);
2730                         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]);
2731                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2732                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2733                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2734                         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]);
2735                 }
2736                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2737                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2738                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2739                 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]);
2740                 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]);
2741
2742                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2743                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2744                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2745                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2746                 {
2747                         if (rsurface.texture->pantstexture)
2748                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2749                         else
2750                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2751                 }
2752                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2753                 {
2754                         if (rsurface.texture->shirttexture)
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2756                         else
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2758                 }
2759                 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]);
2760                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2761                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2762                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2763                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2764                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2765                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2766                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2767                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2768                         );
2769                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2770                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2771                 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]);
2772                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2773                 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);}
2774                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2775
2776                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2777                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2778                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2779                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2780                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2781                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2782                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2785                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2787                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2788                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2789                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2790                 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);
2791                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2792                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2793                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2794                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2795                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2796                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2797                 {
2798                         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);
2799                         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);
2800                         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);
2801                 }
2802                 else
2803                 {
2804                         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);
2805                 }
2806                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2807                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2808                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2809                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2810                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2811                 {
2812                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2813                         if (rsurface.rtlight)
2814                         {
2815                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2816                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2817                         }
2818                 }
2819                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2820                 CHECKGLERROR
2821                 break;
2822         case RENDERPATH_GL11:
2823         case RENDERPATH_GL13:
2824         case RENDERPATH_GLES1:
2825                 break;
2826         case RENDERPATH_SOFT:
2827                 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);
2828                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2829                 R_SetupShader_SetPermutationSoft(mode, permutation);
2830                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2831                 if (mode == SHADERMODE_LIGHTSOURCE)
2832                 {
2833                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2837                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2839         
2840                         // additive passes are only darkened by fog, not tinted
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2842                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2843                 }
2844                 else
2845                 {
2846                         if (mode == SHADERMODE_FLATCOLOR)
2847                         {
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2849                         }
2850                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2851                         {
2852                                 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]);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2854                                 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);
2855                                 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);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2857                                 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]);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2859                         }
2860                         else
2861                         {
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867                         }
2868                         // additive passes are only darkened by fog, not tinted
2869                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2871                         else
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2873                         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);
2874                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2875                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2876                         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]);
2877                         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]);
2878                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2879                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2880                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2881                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2882                 }
2883                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2884                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2885                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2886                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2887                 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]);
2888
2889                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2890                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2891                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2892                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2893                 {
2894                         if (rsurface.texture->pantstexture)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2898                 }
2899                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2900                 {
2901                         if (rsurface.texture->shirttexture)
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2903                         else
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2905                 }
2906                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2907                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2910                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2911                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2912                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2913                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2914                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2915                         );
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2918                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2919                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2920
2921                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2922                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2923                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2924                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2928                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2929                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2930                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2931                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2932                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2933                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2934                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2935                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2936                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2937                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2938                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2939                 {
2940                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2941                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2942                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2943                 }
2944                 else
2945                 {
2946                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2947                 }
2948 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2949 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2951                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2952                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2953                 {
2954                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2955                         if (rsurface.rtlight)
2956                         {
2957                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2958                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2959                         }
2960                 }
2961                 break;
2962         }
2963 }
2964
2965 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2966 {
2967         // select a permutation of the lighting shader appropriate to this
2968         // combination of texture, entity, light source, and fogging, only use the
2969         // minimum features necessary to avoid wasting rendering time in the
2970         // fragment shader on features that are not being used
2971         unsigned int permutation = 0;
2972         unsigned int mode = 0;
2973         const float *lightcolorbase = rtlight->currentcolor;
2974         float ambientscale = rtlight->ambientscale;
2975         float diffusescale = rtlight->diffusescale;
2976         float specularscale = rtlight->specularscale;
2977         // this is the location of the light in view space
2978         vec3_t viewlightorigin;
2979         // this transforms from view space (camera) to light space (cubemap)
2980         matrix4x4_t viewtolight;
2981         matrix4x4_t lighttoview;
2982         float viewtolight16f[16];
2983         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2984         // light source
2985         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2986         if (rtlight->currentcubemap != r_texture_whitecube)
2987                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2988         if (diffusescale > 0)
2989                 permutation |= SHADERPERMUTATION_DIFFUSE;
2990         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2991                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2992         if (r_shadow_usingshadowmap2d)
2993         {
2994                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2995                 if (r_shadow_shadowmapvsdct)
2996                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2997
2998                 if (r_shadow_shadowmapsampler)
2999                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3000                 if (r_shadow_shadowmappcf > 1)
3001                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3002                 else if (r_shadow_shadowmappcf)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3004         }
3005         if (vid.allowalphatocoverage)
3006                 GL_AlphaToCoverage(false);
3007         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3008         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3009         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3010         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3011         switch(vid.renderpath)
3012         {
3013         case RENDERPATH_D3D9:
3014 #ifdef SUPPORTD3D
3015                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3017                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3020                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3021                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3022                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3023                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3024                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3025                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3026
3027                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3028                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3029                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3030                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3031                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3032                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3033 #endif
3034                 break;
3035         case RENDERPATH_D3D10:
3036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3037                 break;
3038         case RENDERPATH_D3D11:
3039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3040                 break;
3041         case RENDERPATH_GL20:
3042         case RENDERPATH_GLES2:
3043                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3044                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3046                 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);
3047                 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);
3048                 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);
3049                 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]);
3050                 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]);
3051                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3052                 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]);
3053                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3054
3055                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3056                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3057                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3058                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3059                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3060                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3061                 break;
3062         case RENDERPATH_GL11:
3063         case RENDERPATH_GL13:
3064         case RENDERPATH_GLES1:
3065                 break;
3066         case RENDERPATH_SOFT:
3067                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3069                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3073                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3074                 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]);
3075                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3076                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3077                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3078
3079                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3080                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3081                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3082                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3083                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3084                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3085                 break;
3086         }
3087 }
3088
3089 #define SKINFRAME_HASH 1024
3090
3091 typedef struct
3092 {
3093         int loadsequence; // incremented each level change
3094         memexpandablearray_t array;
3095         skinframe_t *hash[SKINFRAME_HASH];
3096 }
3097 r_skinframe_t;
3098 r_skinframe_t r_skinframe;
3099
3100 void R_SkinFrame_PrepareForPurge(void)
3101 {
3102         r_skinframe.loadsequence++;
3103         // wrap it without hitting zero
3104         if (r_skinframe.loadsequence >= 200)
3105                 r_skinframe.loadsequence = 1;
3106 }
3107
3108 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3109 {
3110         if (!skinframe)
3111                 return;
3112         // mark the skinframe as used for the purging code
3113         skinframe->loadsequence = r_skinframe.loadsequence;
3114 }
3115
3116 void R_SkinFrame_Purge(void)
3117 {
3118         int i;
3119         skinframe_t *s;
3120         for (i = 0;i < SKINFRAME_HASH;i++)
3121         {
3122                 for (s = r_skinframe.hash[i];s;s = s->next)
3123                 {
3124                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3125                         {
3126                                 if (s->merged == s->base)
3127                                         s->merged = NULL;
3128                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3129                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3130                                 R_PurgeTexture(s->merged);s->merged = NULL;
3131                                 R_PurgeTexture(s->base  );s->base   = NULL;
3132                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3133                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3134                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3135                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3136                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3137                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3138                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3139                                 s->loadsequence = 0;
3140                         }
3141                 }
3142         }
3143 }
3144
3145 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3146         skinframe_t *item;
3147         char basename[MAX_QPATH];
3148
3149         Image_StripImageExtension(name, basename, sizeof(basename));
3150
3151         if( last == NULL ) {
3152                 int hashindex;
3153                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3154                 item = r_skinframe.hash[hashindex];
3155         } else {
3156                 item = last->next;
3157         }
3158
3159         // linearly search through the hash bucket
3160         for( ; item ; item = item->next ) {
3161                 if( !strcmp( item->basename, basename ) ) {
3162                         return item;
3163                 }
3164         }
3165         return NULL;
3166 }
3167
3168 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3169 {
3170         skinframe_t *item;
3171         int hashindex;
3172         char basename[MAX_QPATH];
3173
3174         Image_StripImageExtension(name, basename, sizeof(basename));
3175
3176         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3177         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3178                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3179                         break;
3180
3181         if (!item) {
3182                 rtexture_t *dyntexture;
3183                 // check whether its a dynamic texture
3184                 dyntexture = CL_GetDynTexture( basename );
3185                 if (!add && !dyntexture)
3186                         return NULL;
3187                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3188                 memset(item, 0, sizeof(*item));
3189                 strlcpy(item->basename, basename, sizeof(item->basename));
3190                 item->base = dyntexture; // either NULL or dyntexture handle
3191                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3192                 item->comparewidth = comparewidth;
3193                 item->compareheight = compareheight;
3194                 item->comparecrc = comparecrc;
3195                 item->next = r_skinframe.hash[hashindex];
3196                 r_skinframe.hash[hashindex] = item;
3197         }
3198         else if (textureflags & TEXF_FORCE_RELOAD)
3199         {
3200                 rtexture_t *dyntexture;
3201                 // check whether its a dynamic texture
3202                 dyntexture = CL_GetDynTexture( basename );
3203                 if (!add && !dyntexture)
3204                         return NULL;
3205                 if (item->merged == item->base)
3206                         item->merged = NULL;
3207                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3208                 R_PurgeTexture(item->stain );item->stain  = NULL;
3209                 R_PurgeTexture(item->merged);item->merged = NULL;
3210                 R_PurgeTexture(item->base  );item->base   = NULL;
3211                 R_PurgeTexture(item->pants );item->pants  = NULL;
3212                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3213                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3214                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3215                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3216                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3217         R_PurgeTexture(item->reflect);item->reflect = NULL;
3218                 item->loadsequence = 0;
3219         }
3220         else if( item->base == NULL )
3221         {
3222                 rtexture_t *dyntexture;
3223                 // check whether its a dynamic texture
3224                 // 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]
3225                 dyntexture = CL_GetDynTexture( basename );
3226                 item->base = dyntexture; // either NULL or dyntexture handle
3227         }
3228
3229         R_SkinFrame_MarkUsed(item);
3230         return item;
3231 }
3232
3233 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3234         { \
3235                 unsigned long long avgcolor[5], wsum; \
3236                 int pix, comp, w; \
3237                 avgcolor[0] = 0; \
3238                 avgcolor[1] = 0; \
3239                 avgcolor[2] = 0; \
3240                 avgcolor[3] = 0; \
3241                 avgcolor[4] = 0; \
3242                 wsum = 0; \
3243                 for(pix = 0; pix < cnt; ++pix) \
3244                 { \
3245                         w = 0; \
3246                         for(comp = 0; comp < 3; ++comp) \
3247                                 w += getpixel; \
3248                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3249                         { \
3250                                 ++wsum; \
3251                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3252                                 w = getpixel; \
3253                                 for(comp = 0; comp < 3; ++comp) \
3254                                         avgcolor[comp] += getpixel * w; \
3255                                 avgcolor[3] += w; \
3256                         } \
3257                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3258                         avgcolor[4] += getpixel; \
3259                 } \
3260                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3261                         avgcolor[3] = 1; \
3262                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3264                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3265                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3266         }
3267
3268 extern cvar_t gl_picmip;
3269 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3270 {
3271         int j;
3272         unsigned char *pixels;
3273         unsigned char *bumppixels;
3274         unsigned char *basepixels = NULL;
3275         int basepixels_width = 0;
3276         int basepixels_height = 0;
3277         skinframe_t *skinframe;
3278         rtexture_t *ddsbase = NULL;
3279         qboolean ddshasalpha = false;
3280         float ddsavgcolor[4];
3281         char basename[MAX_QPATH];
3282         int miplevel = R_PicmipForFlags(textureflags);
3283         int savemiplevel = miplevel;
3284         int mymiplevel;
3285
3286         if (cls.state == ca_dedicated)
3287                 return NULL;
3288
3289         // return an existing skinframe if already loaded
3290         // if loading of the first image fails, don't make a new skinframe as it
3291         // would cause all future lookups of this to be missing
3292         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3293         if (skinframe && skinframe->base)
3294                 return skinframe;
3295
3296         Image_StripImageExtension(name, basename, sizeof(basename));
3297
3298         // check for DDS texture file first
3299         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3300         {
3301                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3302                 if (basepixels == NULL)
3303                         return NULL;
3304         }
3305
3306         // FIXME handle miplevel
3307
3308         if (developer_loading.integer)
3309                 Con_Printf("loading skin \"%s\"\n", name);
3310
3311         // we've got some pixels to store, so really allocate this new texture now
3312         if (!skinframe)
3313                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3314         textureflags &= ~TEXF_FORCE_RELOAD;
3315         skinframe->stain = NULL;
3316         skinframe->merged = NULL;
3317         skinframe->base = NULL;
3318         skinframe->pants = NULL;
3319         skinframe->shirt = NULL;
3320         skinframe->nmap = NULL;
3321         skinframe->gloss = NULL;
3322         skinframe->glow = NULL;
3323         skinframe->fog = NULL;
3324         skinframe->reflect = NULL;
3325         skinframe->hasalpha = false;
3326
3327         if (ddsbase)
3328         {
3329                 skinframe->base = ddsbase;
3330                 skinframe->hasalpha = ddshasalpha;
3331                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3332                 if (r_loadfog && skinframe->hasalpha)
3333                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3334                 //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]);
3335         }
3336         else
3337         {
3338                 basepixels_width = image_width;
3339                 basepixels_height = image_height;
3340                 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);
3341                 if (textureflags & TEXF_ALPHA)
3342                 {
3343                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3344                         {
3345                                 if (basepixels[j] < 255)
3346                                 {
3347                                         skinframe->hasalpha = true;
3348                                         break;
3349                                 }
3350                         }
3351                         if (r_loadfog && skinframe->hasalpha)
3352                         {
3353                                 // has transparent pixels
3354                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3355                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3356                                 {
3357                                         pixels[j+0] = 255;
3358                                         pixels[j+1] = 255;
3359                                         pixels[j+2] = 255;
3360                                         pixels[j+3] = basepixels[j+3];
3361                                 }
3362                                 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);
3363                                 Mem_Free(pixels);
3364                         }
3365                 }
3366                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3367 #ifndef USE_GLES2
3368                 //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]);
3369                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3370                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3371                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3372                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3373 #endif
3374         }
3375
3376         if (r_loaddds)
3377         {
3378                 mymiplevel = savemiplevel;
3379                 if (r_loadnormalmap)
3380                         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);
3381                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382                 if (r_loadgloss)
3383                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3385                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3386                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3387         }
3388
3389         // _norm is the name used by tenebrae and has been adopted as standard
3390         if (r_loadnormalmap && skinframe->nmap == NULL)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3394                 {
3395                         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);
3396                         Mem_Free(pixels);
3397                         pixels = NULL;
3398                 }
3399                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3400                 {
3401                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3402                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3403                         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);
3404                         Mem_Free(pixels);
3405                         Mem_Free(bumppixels);
3406                 }
3407                 else if (r_shadow_bumpscale_basetexture.value > 0)
3408                 {
3409                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3410                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3411                         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);
3412                         Mem_Free(pixels);
3413                 }
3414 #ifndef USE_GLES2
3415                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3416                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3417 #endif
3418         }
3419
3420         // _luma is supported only for tenebrae compatibility
3421         // _glow is the preferred name
3422         mymiplevel = savemiplevel;
3423         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))))
3424         {
3425                 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);
3426 #ifndef USE_GLES2
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3428                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3429 #endif
3430                 Mem_Free(pixels);pixels = NULL;
3431         }
3432
3433         mymiplevel = savemiplevel;
3434         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3435         {
3436                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3437 #ifndef USE_GLES2
3438                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3439                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 #endif
3441                 Mem_Free(pixels);
3442                 pixels = NULL;
3443         }
3444
3445         mymiplevel = savemiplevel;
3446         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3447         {
3448                 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);
3449 #ifndef USE_GLES2
3450                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3451                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3452 #endif
3453                 Mem_Free(pixels);
3454                 pixels = NULL;
3455         }
3456
3457         mymiplevel = savemiplevel;
3458         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3459         {
3460                 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);
3461 #ifndef USE_GLES2
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3463                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3464 #endif
3465                 Mem_Free(pixels);
3466                 pixels = NULL;
3467         }
3468
3469         mymiplevel = savemiplevel;
3470         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3471         {
3472                 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);
3473 #ifndef USE_GLES2
3474                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3475                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3476 #endif
3477                 Mem_Free(pixels);
3478                 pixels = NULL;
3479         }
3480
3481         if (basepixels)
3482                 Mem_Free(basepixels);
3483
3484         return skinframe;
3485 }
3486
3487 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3488 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3489 {
3490         int i;
3491         unsigned char *temp1, *temp2;
3492         skinframe_t *skinframe;
3493
3494         if (cls.state == ca_dedicated)
3495                 return NULL;
3496
3497         // if already loaded just return it, otherwise make a new skinframe
3498         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3499         if (skinframe && skinframe->base)
3500                 return skinframe;
3501         textureflags &= ~TEXF_FORCE_RELOAD;
3502
3503         skinframe->stain = NULL;
3504         skinframe->merged = NULL;
3505         skinframe->base = NULL;
3506         skinframe->pants = NULL;
3507         skinframe->shirt = NULL;
3508         skinframe->nmap = NULL;
3509         skinframe->gloss = NULL;
3510         skinframe->glow = NULL;
3511         skinframe->fog = NULL;
3512         skinframe->reflect = NULL;
3513         skinframe->hasalpha = false;
3514
3515         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3516         if (!skindata)
3517                 return NULL;
3518
3519         if (developer_loading.integer)
3520                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3521
3522         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3523         {
3524                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3525                 temp2 = temp1 + width * height * 4;
3526                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3527                 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);
3528                 Mem_Free(temp1);
3529         }
3530         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3531         if (textureflags & TEXF_ALPHA)
3532         {
3533                 for (i = 3;i < width * height * 4;i += 4)
3534                 {
3535                         if (skindata[i] < 255)
3536                         {
3537                                 skinframe->hasalpha = true;
3538                                 break;
3539                         }
3540                 }
3541                 if (r_loadfog && skinframe->hasalpha)
3542                 {
3543                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3544                         memcpy(fogpixels, skindata, width * height * 4);
3545                         for (i = 0;i < width * height * 4;i += 4)
3546                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3547                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3548                         Mem_Free(fogpixels);
3549                 }
3550         }
3551
3552         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3553         //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]);
3554
3555         return skinframe;
3556 }
3557
3558 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3559 {
3560         int i;
3561         int featuresmask;
3562         skinframe_t *skinframe;
3563
3564         if (cls.state == ca_dedicated)
3565                 return NULL;
3566
3567         // if already loaded just return it, otherwise make a new skinframe
3568         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3569         if (skinframe && skinframe->base)
3570                 return skinframe;
3571         textureflags &= ~TEXF_FORCE_RELOAD;
3572
3573         skinframe->stain = NULL;
3574         skinframe->merged = NULL;
3575         skinframe->base = NULL;
3576         skinframe->pants = NULL;
3577         skinframe->shirt = NULL;
3578         skinframe->nmap = NULL;
3579         skinframe->gloss = NULL;
3580         skinframe->glow = NULL;
3581         skinframe->fog = NULL;
3582         skinframe->reflect = NULL;
3583         skinframe->hasalpha = false;
3584
3585         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3586         if (!skindata)
3587                 return NULL;
3588
3589         if (developer_loading.integer)
3590                 Con_Printf("loading quake skin \"%s\"\n", name);
3591
3592         // 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)
3593         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3594         memcpy(skinframe->qpixels, skindata, width*height);
3595         skinframe->qwidth = width;
3596         skinframe->qheight = height;
3597
3598         featuresmask = 0;
3599         for (i = 0;i < width * height;i++)
3600                 featuresmask |= palette_featureflags[skindata[i]];
3601
3602         skinframe->hasalpha = false;
3603         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3604         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3605         skinframe->qgeneratemerged = true;
3606         skinframe->qgeneratebase = skinframe->qhascolormapping;
3607         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3608
3609         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3610         //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]);
3611
3612         return skinframe;
3613 }
3614
3615 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3616 {
3617         int width;
3618         int height;
3619         unsigned char *skindata;
3620
3621         if (!skinframe->qpixels)
3622                 return;
3623
3624         if (!skinframe->qhascolormapping)
3625                 colormapped = false;
3626
3627         if (colormapped)
3628         {
3629                 if (!skinframe->qgeneratebase)
3630                         return;
3631         }
3632         else
3633         {
3634                 if (!skinframe->qgeneratemerged)
3635                         return;
3636         }
3637
3638         width = skinframe->qwidth;
3639         height = skinframe->qheight;
3640         skindata = skinframe->qpixels;
3641
3642         if (skinframe->qgeneratenmap)
3643         {
3644                 unsigned char *temp1, *temp2;
3645                 skinframe->qgeneratenmap = false;
3646                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3647                 temp2 = temp1 + width * height * 4;
3648                 // use either a custom palette or the quake palette
3649                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3650                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3651                 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);
3652                 Mem_Free(temp1);
3653         }
3654
3655         if (skinframe->qgenerateglow)
3656         {
3657                 skinframe->qgenerateglow = false;
3658                 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
3659         }
3660
3661         if (colormapped)
3662         {
3663                 skinframe->qgeneratebase = false;
3664                 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);
3665                 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);
3666                 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);
3667         }
3668         else
3669         {
3670                 skinframe->qgeneratemerged = false;
3671                 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);
3672         }
3673
3674         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3675         {
3676                 Mem_Free(skinframe->qpixels);
3677                 skinframe->qpixels = NULL;
3678         }
3679 }
3680
3681 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)
3682 {
3683         int i;
3684         skinframe_t *skinframe;
3685
3686         if (cls.state == ca_dedicated)
3687                 return NULL;
3688
3689         // if already loaded just return it, otherwise make a new skinframe
3690         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3691         if (skinframe && skinframe->base)
3692                 return skinframe;
3693         textureflags &= ~TEXF_FORCE_RELOAD;
3694
3695         skinframe->stain = NULL;
3696         skinframe->merged = NULL;
3697         skinframe->base = NULL;
3698         skinframe->pants = NULL;
3699         skinframe->shirt = NULL;
3700         skinframe->nmap = NULL;
3701         skinframe->gloss = NULL;
3702         skinframe->glow = NULL;
3703         skinframe->fog = NULL;
3704         skinframe->reflect = NULL;
3705         skinframe->hasalpha = false;
3706
3707         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3708         if (!skindata)
3709                 return NULL;
3710
3711         if (developer_loading.integer)
3712                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3713
3714         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3715         if (textureflags & TEXF_ALPHA)
3716         {
3717                 for (i = 0;i < width * height;i++)
3718                 {
3719                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3720                         {
3721                                 skinframe->hasalpha = true;
3722                                 break;
3723                         }
3724                 }
3725                 if (r_loadfog && skinframe->hasalpha)
3726                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3727         }
3728
3729         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3730         //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]);
3731
3732         return skinframe;
3733 }
3734
3735 skinframe_t *R_SkinFrame_LoadMissing(void)
3736 {
3737         skinframe_t *skinframe;
3738
3739         if (cls.state == ca_dedicated)
3740                 return NULL;
3741
3742         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3743         skinframe->stain = NULL;
3744         skinframe->merged = NULL;
3745         skinframe->base = NULL;
3746         skinframe->pants = NULL;
3747         skinframe->shirt = NULL;
3748         skinframe->nmap = NULL;
3749         skinframe->gloss = NULL;
3750         skinframe->glow = NULL;
3751         skinframe->fog = NULL;
3752         skinframe->reflect = NULL;
3753         skinframe->hasalpha = false;
3754
3755         skinframe->avgcolor[0] = rand() / RAND_MAX;
3756         skinframe->avgcolor[1] = rand() / RAND_MAX;
3757         skinframe->avgcolor[2] = rand() / RAND_MAX;
3758         skinframe->avgcolor[3] = 1;
3759
3760         return skinframe;
3761 }
3762
3763 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3764 typedef struct suffixinfo_s
3765 {
3766         const char *suffix;
3767         qboolean flipx, flipy, flipdiagonal;
3768 }
3769 suffixinfo_t;
3770 static suffixinfo_t suffix[3][6] =
3771 {
3772         {
3773                 {"px",   false, false, false},
3774                 {"nx",   false, false, false},
3775                 {"py",   false, false, false},
3776                 {"ny",   false, false, false},
3777                 {"pz",   false, false, false},
3778                 {"nz",   false, false, false}
3779         },
3780         {
3781                 {"posx", false, false, false},
3782                 {"negx", false, false, false},
3783                 {"posy", false, false, false},
3784                 {"negy", false, false, false},
3785                 {"posz", false, false, false},
3786                 {"negz", false, false, false}
3787         },
3788         {
3789                 {"rt",    true, false,  true},
3790                 {"lf",   false,  true,  true},
3791                 {"ft",    true,  true, false},
3792                 {"bk",   false, false, false},
3793                 {"up",    true, false,  true},
3794                 {"dn",    true, false,  true}
3795         }
3796 };
3797
3798 static int componentorder[4] = {0, 1, 2, 3};
3799
3800 rtexture_t *R_LoadCubemap(const char *basename)
3801 {
3802         int i, j, cubemapsize;
3803         unsigned char *cubemappixels, *image_buffer;
3804         rtexture_t *cubemaptexture;
3805         char name[256];
3806         // must start 0 so the first loadimagepixels has no requested width/height
3807         cubemapsize = 0;
3808         cubemappixels = NULL;
3809         cubemaptexture = NULL;
3810         // keep trying different suffix groups (posx, px, rt) until one loads
3811         for (j = 0;j < 3 && !cubemappixels;j++)
3812         {
3813                 // load the 6 images in the suffix group
3814                 for (i = 0;i < 6;i++)
3815                 {
3816                         // generate an image name based on the base and and suffix
3817                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3818                         // load it
3819                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3820                         {
3821                                 // an image loaded, make sure width and height are equal
3822                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3823                                 {
3824                                         // if this is the first image to load successfully, allocate the cubemap memory
3825                                         if (!cubemappixels && image_width >= 1)
3826                                         {
3827                                                 cubemapsize = image_width;
3828                                                 // note this clears to black, so unavailable sides are black
3829                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3830                                         }
3831                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3832                                         if (cubemappixels)
3833                                                 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);
3834                                 }
3835                                 else
3836                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3837                                 // free the image
3838                                 Mem_Free(image_buffer);
3839                         }
3840                 }
3841         }
3842         // if a cubemap loaded, upload it
3843         if (cubemappixels)
3844         {
3845                 if (developer_loading.integer)
3846                         Con_Printf("loading cubemap \"%s\"\n", basename);
3847
3848                 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);
3849                 Mem_Free(cubemappixels);
3850         }
3851         else
3852         {
3853                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3854                 if (developer_loading.integer)
3855                 {
3856                         Con_Printf("(tried tried images ");
3857                         for (j = 0;j < 3;j++)
3858                                 for (i = 0;i < 6;i++)
3859                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3860                         Con_Print(" and was unable to find any of them).\n");
3861                 }
3862         }
3863         return cubemaptexture;
3864 }
3865
3866 rtexture_t *R_GetCubemap(const char *basename)
3867 {
3868         int i;
3869         for (i = 0;i < r_texture_numcubemaps;i++)
3870                 if (r_texture_cubemaps[i] != NULL)
3871                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3872                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3873         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3874                 return r_texture_whitecube;
3875         r_texture_numcubemaps++;
3876         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3877         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3878         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3879         return r_texture_cubemaps[i]->texture;
3880 }
3881
3882 void R_FreeCubemap(const char *basename)
3883 {
3884         int i;
3885
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887         {
3888                 if (r_texture_cubemaps[i] != NULL)
3889                 {
3890                         if (r_texture_cubemaps[i]->texture)
3891                         {
3892                                 if (developer_loading.integer)
3893                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3894                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3895                                 Mem_Free(r_texture_cubemaps[i]);
3896                                 r_texture_cubemaps[i] = NULL;
3897                         }
3898                 }
3899         }
3900 }
3901
3902 void R_FreeCubemaps(void)
3903 {
3904         int i;
3905         for (i = 0;i < r_texture_numcubemaps;i++)
3906         {
3907                 if (developer_loading.integer)
3908                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3909                 if (r_texture_cubemaps[i] != NULL)
3910                 {
3911                         if (r_texture_cubemaps[i]->texture)
3912                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3913                         Mem_Free(r_texture_cubemaps[i]);
3914                 }
3915         }
3916         r_texture_numcubemaps = 0;
3917 }
3918
3919 void R_Main_FreeViewCache(void)
3920 {
3921         if (r_refdef.viewcache.entityvisible)
3922                 Mem_Free(r_refdef.viewcache.entityvisible);
3923         if (r_refdef.viewcache.world_pvsbits)
3924                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3925         if (r_refdef.viewcache.world_leafvisible)
3926                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3927         if (r_refdef.viewcache.world_surfacevisible)
3928                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3929         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3930 }
3931
3932 void R_Main_ResizeViewCache(void)
3933 {
3934         int numentities = r_refdef.scene.numentities;
3935         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3936         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3937         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3938         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3939         if (r_refdef.viewcache.maxentities < numentities)
3940         {
3941                 r_refdef.viewcache.maxentities = numentities;
3942                 if (r_refdef.viewcache.entityvisible)
3943                         Mem_Free(r_refdef.viewcache.entityvisible);
3944                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3945         }
3946         if (r_refdef.viewcache.world_numclusters != numclusters)
3947         {
3948                 r_refdef.viewcache.world_numclusters = numclusters;
3949                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3950                 if (r_refdef.viewcache.world_pvsbits)
3951                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3952                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3953         }
3954         if (r_refdef.viewcache.world_numleafs != numleafs)
3955         {
3956                 r_refdef.viewcache.world_numleafs = numleafs;
3957                 if (r_refdef.viewcache.world_leafvisible)
3958                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3959                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3960         }
3961         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3962         {
3963                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3964                 if (r_refdef.viewcache.world_surfacevisible)
3965                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3966                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3967         }
3968 }
3969
3970 extern rtexture_t *loadingscreentexture;
3971 void gl_main_start(void)
3972 {
3973         loadingscreentexture = NULL;
3974         r_texture_blanknormalmap = NULL;
3975         r_texture_white = NULL;
3976         r_texture_grey128 = NULL;
3977         r_texture_black = NULL;
3978         r_texture_whitecube = NULL;
3979         r_texture_normalizationcube = NULL;
3980         r_texture_fogattenuation = NULL;
3981         r_texture_fogheighttexture = NULL;
3982         r_texture_gammaramps = NULL;
3983         r_texture_numcubemaps = 0;
3984
3985         r_loaddds = r_texture_dds_load.integer != 0;
3986         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3987
3988         switch(vid.renderpath)
3989         {
3990         case RENDERPATH_GL20:
3991         case RENDERPATH_D3D9:
3992         case RENDERPATH_D3D10:
3993         case RENDERPATH_D3D11:
3994         case RENDERPATH_SOFT:
3995         case RENDERPATH_GLES2:
3996                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3997                 Cvar_SetValueQuick(&gl_combine, 1);
3998                 Cvar_SetValueQuick(&r_glsl, 1);
3999                 r_loadnormalmap = true;
4000                 r_loadgloss = true;
4001                 r_loadfog = false;
4002                 break;
4003         case RENDERPATH_GL13:
4004         case RENDERPATH_GLES1:
4005                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006                 Cvar_SetValueQuick(&gl_combine, 1);
4007                 Cvar_SetValueQuick(&r_glsl, 0);
4008                 r_loadnormalmap = false;
4009                 r_loadgloss = false;
4010                 r_loadfog = true;
4011                 break;
4012         case RENDERPATH_GL11:
4013                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4014                 Cvar_SetValueQuick(&gl_combine, 0);
4015                 Cvar_SetValueQuick(&r_glsl, 0);
4016                 r_loadnormalmap = false;
4017                 r_loadgloss = false;
4018                 r_loadfog = true;
4019                 break;
4020         }
4021
4022         R_AnimCache_Free();
4023         R_FrameData_Reset();
4024
4025         r_numqueries = 0;
4026         r_maxqueries = 0;
4027         memset(r_queries, 0, sizeof(r_queries));
4028
4029         r_qwskincache = NULL;
4030         r_qwskincache_size = 0;
4031
4032         // due to caching of texture_t references, the collision cache must be reset
4033         Collision_Cache_Reset(true);
4034
4035         // set up r_skinframe loading system for textures
4036         memset(&r_skinframe, 0, sizeof(r_skinframe));
4037         r_skinframe.loadsequence = 1;
4038         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4039
4040         r_main_texturepool = R_AllocTexturePool();
4041         R_BuildBlankTextures();
4042         R_BuildNoTexture();
4043         if (vid.support.arb_texture_cube_map)
4044         {
4045                 R_BuildWhiteCube();
4046                 R_BuildNormalizationCube();
4047         }
4048         r_texture_fogattenuation = NULL;
4049         r_texture_fogheighttexture = NULL;
4050         r_texture_gammaramps = NULL;
4051         //r_texture_fogintensity = NULL;
4052         memset(&r_fb, 0, sizeof(r_fb));
4053         r_glsl_permutation = NULL;
4054         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4055         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4056         glslshaderstring = NULL;
4057 #ifdef SUPPORTD3D
4058         r_hlsl_permutation = NULL;
4059         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4060         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4061 #endif
4062         hlslshaderstring = NULL;
4063         memset(&r_svbsp, 0, sizeof (r_svbsp));
4064
4065         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4066         r_texture_numcubemaps = 0;
4067
4068         r_refdef.fogmasktable_density = 0;
4069 }
4070
4071 void gl_main_shutdown(void)
4072 {
4073         R_AnimCache_Free();
4074         R_FrameData_Reset();
4075
4076         R_Main_FreeViewCache();
4077
4078         switch(vid.renderpath)
4079         {
4080         case RENDERPATH_GL11:
4081         case RENDERPATH_GL13:
4082         case RENDERPATH_GL20:
4083         case RENDERPATH_GLES1:
4084         case RENDERPATH_GLES2:
4085 #ifdef GL_SAMPLES_PASSED_ARB
4086                 if (r_maxqueries)
4087                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4088 #endif
4089                 break;
4090         case RENDERPATH_D3D9:
4091                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4092                 break;
4093         case RENDERPATH_D3D10:
4094                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4095                 break;
4096         case RENDERPATH_D3D11:
4097                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4098                 break;
4099         case RENDERPATH_SOFT:
4100                 break;
4101         }
4102
4103         r_numqueries = 0;
4104         r_maxqueries = 0;
4105         memset(r_queries, 0, sizeof(r_queries));
4106
4107         r_qwskincache = NULL;
4108         r_qwskincache_size = 0;
4109
4110         // clear out the r_skinframe state
4111         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4112         memset(&r_skinframe, 0, sizeof(r_skinframe));
4113
4114         if (r_svbsp.nodes)
4115                 Mem_Free(r_svbsp.nodes);
4116         memset(&r_svbsp, 0, sizeof (r_svbsp));
4117         R_FreeTexturePool(&r_main_texturepool);
4118         loadingscreentexture = NULL;
4119         r_texture_blanknormalmap = NULL;
4120         r_texture_white = NULL;
4121         r_texture_grey128 = NULL;
4122         r_texture_black = NULL;
4123         r_texture_whitecube = NULL;
4124         r_texture_normalizationcube = NULL;
4125         r_texture_fogattenuation = NULL;
4126         r_texture_fogheighttexture = NULL;
4127         r_texture_gammaramps = NULL;
4128         r_texture_numcubemaps = 0;
4129         //r_texture_fogintensity = NULL;
4130         memset(&r_fb, 0, sizeof(r_fb));
4131         R_GLSL_Restart_f();
4132
4133         r_glsl_permutation = NULL;
4134         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4135         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4136         glslshaderstring = NULL;
4137 #ifdef SUPPORTD3D
4138         r_hlsl_permutation = NULL;
4139         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4140         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4141 #endif
4142         hlslshaderstring = NULL;
4143 }
4144
4145 extern void CL_ParseEntityLump(char *entitystring);
4146 void gl_main_newmap(void)
4147 {
4148         // FIXME: move this code to client
4149         char *entities, entname[MAX_QPATH];
4150         if (r_qwskincache)
4151                 Mem_Free(r_qwskincache);
4152         r_qwskincache = NULL;
4153         r_qwskincache_size = 0;
4154         if (cl.worldmodel)
4155         {
4156                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4157                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4158                 {
4159                         CL_ParseEntityLump(entities);
4160                         Mem_Free(entities);
4161                         return;
4162                 }
4163                 if (cl.worldmodel->brush.entities)
4164                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4165         }
4166         R_Main_FreeViewCache();
4167
4168         R_FrameData_Reset();
4169 }
4170
4171 void GL_Main_Init(void)
4172 {
4173         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4174
4175         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4176         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4177         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4178         if (gamemode == GAME_NEHAHRA)
4179         {
4180                 Cvar_RegisterVariable (&gl_fogenable);
4181                 Cvar_RegisterVariable (&gl_fogdensity);
4182                 Cvar_RegisterVariable (&gl_fogred);
4183                 Cvar_RegisterVariable (&gl_foggreen);
4184                 Cvar_RegisterVariable (&gl_fogblue);
4185                 Cvar_RegisterVariable (&gl_fogstart);
4186                 Cvar_RegisterVariable (&gl_fogend);
4187                 Cvar_RegisterVariable (&gl_skyclip);
4188         }
4189         Cvar_RegisterVariable(&r_motionblur);
4190         Cvar_RegisterVariable(&r_damageblur);
4191         Cvar_RegisterVariable(&r_motionblur_averaging);
4192         Cvar_RegisterVariable(&r_motionblur_randomize);
4193         Cvar_RegisterVariable(&r_motionblur_minblur);
4194         Cvar_RegisterVariable(&r_motionblur_maxblur);
4195         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4196         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4197         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4198         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4199         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4200         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4201         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4202         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4203         Cvar_RegisterVariable(&r_equalize_entities_by);
4204         Cvar_RegisterVariable(&r_equalize_entities_to);
4205         Cvar_RegisterVariable(&r_depthfirst);
4206         Cvar_RegisterVariable(&r_useinfinitefarclip);
4207         Cvar_RegisterVariable(&r_farclip_base);
4208         Cvar_RegisterVariable(&r_farclip_world);
4209         Cvar_RegisterVariable(&r_nearclip);
4210         Cvar_RegisterVariable(&r_deformvertexes);
4211         Cvar_RegisterVariable(&r_transparent);
4212         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4213         Cvar_RegisterVariable(&r_showoverdraw);
4214         Cvar_RegisterVariable(&r_showbboxes);
4215         Cvar_RegisterVariable(&r_showsurfaces);
4216         Cvar_RegisterVariable(&r_showtris);
4217         Cvar_RegisterVariable(&r_shownormals);
4218         Cvar_RegisterVariable(&r_showlighting);
4219         Cvar_RegisterVariable(&r_showshadowvolumes);
4220         Cvar_RegisterVariable(&r_showcollisionbrushes);
4221         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4222         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4223         Cvar_RegisterVariable(&r_showdisabledepthtest);
4224         Cvar_RegisterVariable(&r_drawportals);
4225         Cvar_RegisterVariable(&r_drawentities);
4226         Cvar_RegisterVariable(&r_draw2d);
4227         Cvar_RegisterVariable(&r_drawworld);
4228         Cvar_RegisterVariable(&r_cullentities_trace);
4229         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4230         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4231         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4232         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4233         Cvar_RegisterVariable(&r_sortentities);
4234         Cvar_RegisterVariable(&r_drawviewmodel);
4235         Cvar_RegisterVariable(&r_drawexteriormodel);
4236         Cvar_RegisterVariable(&r_speeds);
4237         Cvar_RegisterVariable(&r_fullbrights);
4238         Cvar_RegisterVariable(&r_wateralpha);
4239         Cvar_RegisterVariable(&r_dynamic);
4240         Cvar_RegisterVariable(&r_fakelight);
4241         Cvar_RegisterVariable(&r_fakelight_intensity);
4242         Cvar_RegisterVariable(&r_fullbright);
4243         Cvar_RegisterVariable(&r_shadows);
4244         Cvar_RegisterVariable(&r_shadows_darken);
4245         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4246         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4247         Cvar_RegisterVariable(&r_shadows_throwdistance);
4248         Cvar_RegisterVariable(&r_shadows_throwdirection);
4249         Cvar_RegisterVariable(&r_shadows_focus);
4250         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4251         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4252         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4253         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4254         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4255         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4256         Cvar_RegisterVariable(&r_fog_exp2);
4257         Cvar_RegisterVariable(&r_fog_clear);
4258         Cvar_RegisterVariable(&r_drawfog);
4259         Cvar_RegisterVariable(&r_transparentdepthmasking);
4260         Cvar_RegisterVariable(&r_transparent_sortmindist);
4261         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4262         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4263         Cvar_RegisterVariable(&r_texture_dds_load);
4264         Cvar_RegisterVariable(&r_texture_dds_save);
4265         Cvar_RegisterVariable(&r_textureunits);
4266         Cvar_RegisterVariable(&gl_combine);
4267         Cvar_RegisterVariable(&r_viewfbo);
4268         Cvar_RegisterVariable(&r_viewscale);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4272         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4273         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4274         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4275         Cvar_RegisterVariable(&r_glsl);
4276         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4283         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4285         Cvar_RegisterVariable(&r_glsl_postprocess);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4292         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4294
4295         Cvar_RegisterVariable(&r_water);
4296         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4297         Cvar_RegisterVariable(&r_water_clippingplanebias);
4298         Cvar_RegisterVariable(&r_water_refractdistort);
4299         Cvar_RegisterVariable(&r_water_reflectdistort);
4300         Cvar_RegisterVariable(&r_water_scissormode);
4301         Cvar_RegisterVariable(&r_water_lowquality);
4302         Cvar_RegisterVariable(&r_water_hideplayer);
4303
4304         Cvar_RegisterVariable(&r_lerpsprites);
4305         Cvar_RegisterVariable(&r_lerpmodels);
4306         Cvar_RegisterVariable(&r_lerplightstyles);
4307         Cvar_RegisterVariable(&r_waterscroll);
4308         Cvar_RegisterVariable(&r_bloom);
4309         Cvar_RegisterVariable(&r_bloom_colorscale);
4310         Cvar_RegisterVariable(&r_bloom_brighten);
4311         Cvar_RegisterVariable(&r_bloom_blur);
4312         Cvar_RegisterVariable(&r_bloom_resolution);
4313         Cvar_RegisterVariable(&r_bloom_colorexponent);
4314         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4315         Cvar_RegisterVariable(&r_hdr);
4316         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4317         Cvar_RegisterVariable(&r_hdr_glowintensity);
4318         Cvar_RegisterVariable(&r_hdr_range);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4324         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4327         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4328         Cvar_RegisterVariable(&developer_texturelogging);
4329         Cvar_RegisterVariable(&gl_lightmaps);
4330         Cvar_RegisterVariable(&r_test);
4331         Cvar_RegisterVariable(&r_glsl_saturation);
4332         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4333         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4334         Cvar_RegisterVariable(&r_framedatasize);
4335         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4336                 Cvar_SetValue("r_fullbrights", 0);
4337         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4338 }
4339
4340 extern void R_Textures_Init(void);
4341 extern void GL_Draw_Init(void);
4342 extern void GL_Main_Init(void);
4343 extern void R_Shadow_Init(void);
4344 extern void R_Sky_Init(void);
4345 extern void GL_Surf_Init(void);
4346 extern void R_Particles_Init(void);
4347 extern void R_Explosion_Init(void);
4348 extern void gl_backend_init(void);
4349 extern void Sbar_Init(void);
4350 extern void R_LightningBeams_Init(void);
4351 extern void Mod_RenderInit(void);
4352 extern void Font_Init(void);
4353
4354 void Render_Init(void)
4355 {
4356         gl_backend_init();
4357         R_Textures_Init();
4358         GL_Main_Init();
4359         Font_Init();
4360         GL_Draw_Init();
4361         R_Shadow_Init();
4362         R_Sky_Init();
4363         GL_Surf_Init();
4364         Sbar_Init();
4365         R_Particles_Init();
4366         R_Explosion_Init();
4367         R_LightningBeams_Init();
4368         Mod_RenderInit();
4369 }
4370
4371 /*
4372 ===============
4373 GL_Init
4374 ===============
4375 */
4376 #ifndef USE_GLES2
4377 extern char *ENGINE_EXTENSIONS;
4378 void GL_Init (void)
4379 {
4380         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4381         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4382         gl_version = (const char *)qglGetString(GL_VERSION);
4383         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4384
4385         if (!gl_extensions)
4386                 gl_extensions = "";
4387         if (!gl_platformextensions)
4388                 gl_platformextensions = "";
4389
4390         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4391         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4392         Con_Printf("GL_VERSION: %s\n", gl_version);
4393         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4394         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4395
4396         VID_CheckExtensions();
4397
4398         // LordHavoc: report supported extensions
4399         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4400
4401         // clear to black (loading plaque will be seen over this)
4402         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4403 }
4404 #endif
4405
4406 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4407 {
4408         int i;
4409         mplane_t *p;
4410         if (r_trippy.integer)
4411                 return false;
4412         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4413         {
4414                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4415                 if (i == 4)
4416                         continue;
4417                 p = r_refdef.view.frustum + i;
4418                 switch(p->signbits)
4419                 {
4420                 default:
4421                 case 0:
4422                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 1:
4426                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 2:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 3:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 4:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 5:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 6:
4446                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 7:
4450                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 }
4454         }
4455         return false;
4456 }
4457
4458 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4459 {
4460         int i;
4461         const mplane_t *p;
4462         if (r_trippy.integer)
4463                 return false;
4464         for (i = 0;i < numplanes;i++)
4465         {
4466                 p = planes + i;
4467                 switch(p->signbits)
4468                 {
4469                 default:
4470                 case 0:
4471                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 1:
4475                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 2:
4479                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 3:
4483                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 4:
4487                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 5:
4491                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 6:
4495                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 case 7:
4499                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4500                                 return true;
4501                         break;
4502                 }
4503         }
4504         return false;
4505 }
4506
4507 //==================================================================================
4508
4509 // LordHavoc: this stores temporary data used within the same frame
4510
4511 typedef struct r_framedata_mem_s
4512 {
4513         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4514         size_t size; // how much usable space
4515         size_t current; // how much space in use
4516         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4517         size_t wantedsize; // how much space was allocated
4518         unsigned char *data; // start of real data (16byte aligned)
4519 }
4520 r_framedata_mem_t;
4521
4522 static r_framedata_mem_t *r_framedata_mem;
4523
4524 void R_FrameData_Reset(void)
4525 {
4526         while (r_framedata_mem)
4527         {
4528                 r_framedata_mem_t *next = r_framedata_mem->purge;
4529                 Mem_Free(r_framedata_mem);
4530                 r_framedata_mem = next;
4531         }
4532 }
4533
4534 void R_FrameData_Resize(void)
4535 {
4536         size_t wantedsize;
4537         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4538         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4539         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4540         {
4541                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4542                 newmem->wantedsize = wantedsize;
4543                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4544                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4545                 newmem->current = 0;
4546                 newmem->mark = 0;
4547                 newmem->purge = r_framedata_mem;
4548                 r_framedata_mem = newmem;
4549         }
4550 }
4551
4552 void R_FrameData_NewFrame(void)
4553 {
4554         R_FrameData_Resize();
4555         if (!r_framedata_mem)
4556                 return;
4557         // if we ran out of space on the last frame, free the old memory now
4558         while (r_framedata_mem->purge)
4559         {
4560                 // repeatedly remove the second item in the list, leaving only head
4561                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4562                 Mem_Free(r_framedata_mem->purge);
4563                 r_framedata_mem->purge = next;
4564         }
4565         // reset the current mem pointer
4566         r_framedata_mem->current = 0;
4567         r_framedata_mem->mark = 0;
4568 }
4569
4570 void *R_FrameData_Alloc(size_t size)
4571 {
4572         void *data;
4573
4574         // align to 16 byte boundary - the data pointer is already aligned, so we
4575         // only need to ensure the size of every allocation is also aligned
4576         size = (size + 15) & ~15;
4577
4578         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4579         {
4580                 // emergency - we ran out of space, allocate more memory
4581                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4582                 R_FrameData_Resize();
4583         }
4584
4585         data = r_framedata_mem->data + r_framedata_mem->current;
4586         r_framedata_mem->current += size;
4587
4588         // count the usage for stats
4589         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4590         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4591
4592         return (void *)data;
4593 }
4594
4595 void *R_FrameData_Store(size_t size, void *data)
4596 {
4597         void *d = R_FrameData_Alloc(size);
4598         if (d && data)
4599                 memcpy(d, data, size);
4600         return d;
4601 }
4602
4603 void R_FrameData_SetMark(void)
4604 {
4605         if (!r_framedata_mem)
4606                 return;
4607         r_framedata_mem->mark = r_framedata_mem->current;
4608 }
4609
4610 void R_FrameData_ReturnToMark(void)
4611 {
4612         if (!r_framedata_mem)
4613                 return;
4614         r_framedata_mem->current = r_framedata_mem->mark;
4615 }
4616
4617 //==================================================================================
4618
4619 // LordHavoc: animcache originally written by Echon, rewritten since then
4620
4621 /**
4622  * Animation cache prevents re-generating mesh data for an animated model
4623  * multiple times in one frame for lighting, shadowing, reflections, etc.
4624  */
4625
4626 void R_AnimCache_Free(void)
4627 {
4628 }
4629
4630 void R_AnimCache_ClearCache(void)
4631 {
4632         int i;
4633         entity_render_t *ent;
4634
4635         for (i = 0;i < r_refdef.scene.numentities;i++)
4636         {
4637                 ent = r_refdef.scene.entities[i];
4638                 ent->animcache_vertex3f = NULL;
4639                 ent->animcache_normal3f = NULL;
4640                 ent->animcache_svector3f = NULL;
4641                 ent->animcache_tvector3f = NULL;
4642                 ent->animcache_vertexmesh = NULL;
4643                 ent->animcache_vertex3fbuffer = NULL;
4644                 ent->animcache_vertexmeshbuffer = NULL;
4645         }
4646 }
4647
4648 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4649 {
4650         int i;
4651
4652         // check if we need the meshbuffers
4653         if (!vid.useinterleavedarrays)
4654                 return;
4655
4656         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4657                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4658         // TODO: upload vertex3f buffer?
4659         if (ent->animcache_vertexmesh)
4660         {
4661                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4662                 for (i = 0;i < numvertices;i++)
4663                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4664                 if (ent->animcache_svector3f)
4665                         for (i = 0;i < numvertices;i++)
4666                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4667                 if (ent->animcache_tvector3f)
4668                         for (i = 0;i < numvertices;i++)
4669                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4670                 if (ent->animcache_normal3f)
4671                         for (i = 0;i < numvertices;i++)
4672                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4673                 // TODO: upload vertexmeshbuffer?
4674         }
4675 }
4676
4677 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4678 {
4679         dp_model_t *model = ent->model;
4680         int numvertices;
4681         // see if it's already cached this frame
4682         if (ent->animcache_vertex3f)
4683         {
4684                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4685                 if (wantnormals || wanttangents)
4686                 {
4687                         if (ent->animcache_normal3f)
4688                                 wantnormals = false;
4689                         if (ent->animcache_svector3f)
4690                                 wanttangents = false;
4691                         if (wantnormals || wanttangents)
4692                         {
4693                                 numvertices = model->surfmesh.num_vertices;
4694                                 if (wantnormals)
4695                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4696                                 if (wanttangents)
4697                                 {
4698                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4699                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4700                                 }
4701                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4702                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4703                         }
4704                 }
4705         }
4706         else
4707         {
4708                 // see if this ent is worth caching
4709                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4710                         return false;
4711                 // get some memory for this entity and generate mesh data
4712                 numvertices = model->surfmesh.num_vertices;
4713                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4714                 if (wantnormals)
4715                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4716                 if (wanttangents)
4717                 {
4718                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720                 }
4721                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4722                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4723         }
4724         return true;
4725 }
4726
4727 void R_AnimCache_CacheVisibleEntities(void)
4728 {
4729         int i;
4730         qboolean wantnormals = true;
4731         qboolean wanttangents = !r_showsurfaces.integer;
4732
4733         switch(vid.renderpath)
4734         {
4735         case RENDERPATH_GL20:
4736         case RENDERPATH_D3D9:
4737         case RENDERPATH_D3D10:
4738         case RENDERPATH_D3D11:
4739         case RENDERPATH_GLES2:
4740                 break;
4741         case RENDERPATH_GL11:
4742         case RENDERPATH_GL13:
4743         case RENDERPATH_GLES1:
4744                 wanttangents = false;
4745                 break;
4746         case RENDERPATH_SOFT:
4747                 break;
4748         }
4749
4750         if (r_shownormals.integer)
4751                 wanttangents = wantnormals = true;
4752
4753         // TODO: thread this
4754         // NOTE: R_PrepareRTLights() also caches entities
4755
4756         for (i = 0;i < r_refdef.scene.numentities;i++)
4757                 if (r_refdef.viewcache.entityvisible[i])
4758                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4759 }
4760
4761 //==================================================================================
4762
4763 extern cvar_t r_overheadsprites_pushback;
4764
4765 static void R_View_UpdateEntityLighting (void)
4766 {
4767         int i;
4768         entity_render_t *ent;
4769         vec3_t tempdiffusenormal, avg;
4770         vec_t f, fa, fd, fdd;
4771         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4772
4773         for (i = 0;i < r_refdef.scene.numentities;i++)
4774         {
4775                 ent = r_refdef.scene.entities[i];
4776
4777                 // skip unseen models and models that updated by CSQC
4778                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4779                         continue;
4780
4781                 // skip bsp models
4782                 if (ent->model && ent->model->brush.num_leafs)
4783                 {
4784                         // TODO: use modellight for r_ambient settings on world?
4785                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4786                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4787                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4788                         continue;
4789                 }
4790
4791                 // fetch the lighting from the worldmodel data
4792                 VectorClear(ent->modellight_ambient);
4793                 VectorClear(ent->modellight_diffuse);
4794                 VectorClear(tempdiffusenormal);
4795                 if (ent->flags & RENDER_LIGHT)
4796                 {
4797                         vec3_t org;
4798                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4799
4800                         // complete lightning for lit sprites
4801                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4802                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4803                         {
4804                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4805                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4806                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4807                         }
4808                         else
4809                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4810
4811                         if(ent->flags & RENDER_EQUALIZE)
4812                         {
4813                                 // first fix up ambient lighting...
4814                                 if(r_equalize_entities_minambient.value > 0)
4815                                 {
4816                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4817                                         if(fd > 0)
4818                                         {
4819                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4820                                                 if(fa < r_equalize_entities_minambient.value * fd)
4821                                                 {
4822                                                         // solve:
4823                                                         //   fa'/fd' = minambient
4824                                                         //   fa'+0.25*fd' = fa+0.25*fd
4825                                                         //   ...
4826                                                         //   fa' = fd' * minambient
4827                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4828                                                         //   ...
4829                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4830                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4831                                                         //   ...
4832                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4833                                                         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
4834                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4835                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4836                                                 }
4837                                         }
4838                                 }
4839
4840                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4841                                 {
4842                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4843                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4844                                         f = fa + 0.25 * fd;
4845                                         if(f > 0)
4846                                         {
4847                                                 // adjust brightness and saturation to target
4848                                                 avg[0] = avg[1] = avg[2] = fa / f;
4849                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4850                                                 avg[0] = avg[1] = avg[2] = fd / f;
4851                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4852                                         }
4853                                 }
4854                         }
4855                 }
4856                 else // highly rare
4857                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4858
4859                 // move the light direction into modelspace coordinates for lighting code
4860                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4861                 if(VectorLength2(ent->modellight_lightdir) == 0)
4862                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4863                 VectorNormalize(ent->modellight_lightdir);
4864         }
4865 }
4866
4867 #define MAX_LINEOFSIGHTTRACES 64
4868
4869 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4870 {
4871         int i;
4872         vec3_t boxmins, boxmaxs;
4873         vec3_t start;
4874         vec3_t end;
4875         dp_model_t *model = r_refdef.scene.worldmodel;
4876
4877         if (!model || !model->brush.TraceLineOfSight)
4878                 return true;
4879
4880         // expand the box a little
4881         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4882         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4883         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4884         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4885         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4886         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4887
4888         // return true if eye is inside enlarged box
4889         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4890                 return true;
4891
4892         // try center
4893         VectorCopy(eye, start);
4894         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4895         if (model->brush.TraceLineOfSight(model, start, end))
4896                 return true;
4897
4898         // try various random positions
4899         for (i = 0;i < numsamples;i++)
4900         {
4901                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4902                 if (model->brush.TraceLineOfSight(model, start, end))
4903                         return true;
4904         }
4905
4906         return false;
4907 }
4908
4909
4910 static void R_View_UpdateEntityVisible (void)
4911 {
4912         int i;
4913         int renderimask;
4914         int samples;
4915         entity_render_t *ent;
4916
4917         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4918                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4919                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4920                 :                                                          RENDER_EXTERIORMODEL;
4921         if (!r_drawviewmodel.integer)
4922                 renderimask |= RENDER_VIEWMODEL;
4923         if (!r_drawexteriormodel.integer)
4924                 renderimask |= RENDER_EXTERIORMODEL;
4925         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4926         {
4927                 // worldmodel can check visibility
4928                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4929                 for (i = 0;i < r_refdef.scene.numentities;i++)
4930                 {
4931                         ent = r_refdef.scene.entities[i];
4932                         if (!(ent->flags & renderimask))
4933                         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)))
4934                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_WORLDOBJECT | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4935                                 r_refdef.viewcache.entityvisible[i] = true;
4936                 }
4937         }
4938         else
4939         {
4940                 // no worldmodel or it can't check visibility
4941                 for (i = 0;i < r_refdef.scene.numentities;i++)
4942                 {
4943                         ent = r_refdef.scene.entities[i];
4944                         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));
4945                 }
4946         }
4947         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4948                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4949         {
4950                 for (i = 0;i < r_refdef.scene.numentities;i++)
4951                 {
4952                         if (!r_refdef.viewcache.entityvisible[i])
4953                                 continue;
4954                         ent = r_refdef.scene.entities[i];
4955                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4956                         {
4957                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4958                                 if (samples < 0)
4959                                         continue; // temp entities do pvs only
4960                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4961                                         ent->last_trace_visibility = realtime;
4962                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4963                                         r_refdef.viewcache.entityvisible[i] = 0;
4964                         }
4965                 }
4966         }
4967 }
4968
4969 /// only used if skyrendermasked, and normally returns false
4970 int R_DrawBrushModelsSky (void)
4971 {
4972         int i, sky;
4973         entity_render_t *ent;
4974
4975         sky = false;
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 if (!ent->model || !ent->model->DrawSky)
4982                         continue;
4983                 ent->model->DrawSky(ent);
4984                 sky = true;
4985         }
4986         return sky;
4987 }
4988
4989 static void R_DrawNoModel(entity_render_t *ent);
4990 static void R_DrawModels(void)
4991 {
4992         int i;
4993         entity_render_t *ent;
4994
4995         for (i = 0;i < r_refdef.scene.numentities;i++)
4996         {
4997                 if (!r_refdef.viewcache.entityvisible[i])
4998                         continue;
4999                 ent = r_refdef.scene.entities[i];
5000                 r_refdef.stats.entities++;
5001                 /*
5002                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5003                 {
5004                         vec3_t f, l, u, o;
5005                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5006                         Con_Printf("R_DrawModels\n");
5007                         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]);
5008                         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);
5009                         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);
5010                 }
5011                 */
5012                 if (ent->model && ent->model->Draw != NULL)
5013                         ent->model->Draw(ent);
5014                 else
5015                         R_DrawNoModel(ent);
5016         }
5017 }
5018
5019 static void R_DrawModelsDepth(void)
5020 {
5021         int i;
5022         entity_render_t *ent;
5023
5024         for (i = 0;i < r_refdef.scene.numentities;i++)
5025         {
5026                 if (!r_refdef.viewcache.entityvisible[i])
5027                         continue;
5028                 ent = r_refdef.scene.entities[i];
5029                 if (ent->model && ent->model->DrawDepth != NULL)
5030                         ent->model->DrawDepth(ent);
5031         }
5032 }
5033
5034 static void R_DrawModelsDebug(void)
5035 {
5036         int i;
5037         entity_render_t *ent;
5038
5039         for (i = 0;i < r_refdef.scene.numentities;i++)
5040         {
5041                 if (!r_refdef.viewcache.entityvisible[i])
5042                         continue;
5043                 ent = r_refdef.scene.entities[i];
5044                 if (ent->model && ent->model->DrawDebug != NULL)
5045                         ent->model->DrawDebug(ent);
5046         }
5047 }
5048
5049 static void R_DrawModelsAddWaterPlanes(void)
5050 {
5051         int i;
5052         entity_render_t *ent;
5053
5054         for (i = 0;i < r_refdef.scene.numentities;i++)
5055         {
5056                 if (!r_refdef.viewcache.entityvisible[i])
5057                         continue;
5058                 ent = r_refdef.scene.entities[i];
5059                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5060                         ent->model->DrawAddWaterPlanes(ent);
5061         }
5062 }
5063
5064 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5065
5066 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5067 {
5068         if (r_hdr_irisadaptation.integer)
5069         {
5070                 vec3_t p;
5071                 vec3_t ambient;
5072                 vec3_t diffuse;
5073                 vec3_t diffusenormal;
5074                 vec3_t forward;
5075                 vec_t brightness = 0.0f;
5076                 vec_t goal;
5077                 vec_t current;
5078                 vec_t d;
5079                 int c;
5080                 VectorCopy(r_refdef.view.forward, forward);
5081                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5082                 {
5083                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5084                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5085                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5086                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5087                         d = DotProduct(forward, diffusenormal);
5088                         brightness += VectorLength(ambient);
5089                         if (d > 0)
5090                                 brightness += d * VectorLength(diffuse);
5091                 }
5092                 brightness *= 1.0f / c;
5093                 brightness += 0.00001f; // make sure it's never zero
5094                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5095                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5096                 current = r_hdr_irisadaptation_value.value;
5097                 if (current < goal)
5098                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5099                 else if (current > goal)
5100                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5101                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5102                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5103         }
5104         else if (r_hdr_irisadaptation_value.value != 1.0f)
5105                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5106 }
5107
5108 static void R_View_SetFrustum(const int *scissor)
5109 {
5110         int i;
5111         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5112         vec3_t forward, left, up, origin, v;
5113
5114         if(scissor)
5115         {
5116                 // flipped x coordinates (because x points left here)
5117                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5118                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5119
5120                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5121                 switch(vid.renderpath)
5122                 {
5123                         case RENDERPATH_D3D9:
5124                         case RENDERPATH_D3D10:
5125                         case RENDERPATH_D3D11:
5126                                 // non-flipped y coordinates
5127                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5128                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5129                                 break;
5130                         case RENDERPATH_SOFT:
5131                         case RENDERPATH_GL11:
5132                         case RENDERPATH_GL13:
5133                         case RENDERPATH_GL20:
5134                         case RENDERPATH_GLES1:
5135                         case RENDERPATH_GLES2:
5136                                 // non-flipped y coordinates
5137                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5138                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5139                                 break;
5140                 }
5141         }
5142
5143         // we can't trust r_refdef.view.forward and friends in reflected scenes
5144         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5145
5146 #if 0
5147         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5148         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5149         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5150         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5151         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5152         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5153         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5154         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5155         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5156         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5157         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5158         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5159 #endif
5160
5161 #if 0
5162         zNear = r_refdef.nearclip;
5163         nudge = 1.0 - 1.0 / (1<<23);
5164         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5165         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5166         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5167         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5168         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5169         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5170         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5171         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5172 #endif
5173
5174
5175
5176 #if 0
5177         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5178         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5179         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5180         r_refdef.view.frustum[0].dist = m[15] - m[12];
5181
5182         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5183         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5184         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5185         r_refdef.view.frustum[1].dist = m[15] + m[12];
5186
5187         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5188         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5189         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5190         r_refdef.view.frustum[2].dist = m[15] - m[13];
5191
5192         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5193         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5194         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5195         r_refdef.view.frustum[3].dist = m[15] + m[13];
5196
5197         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5198         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5199         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5200         r_refdef.view.frustum[4].dist = m[15] - m[14];
5201
5202         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5203         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5204         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5205         r_refdef.view.frustum[5].dist = m[15] + m[14];
5206 #endif
5207
5208         if (r_refdef.view.useperspective)
5209         {
5210                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5211                 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]);
5212                 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]);
5213                 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]);
5214                 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]);
5215
5216                 // then the normals from the corners relative to origin
5217                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5218                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5219                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5220                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5221
5222                 // in a NORMAL view, forward cross left == up
5223                 // in a REFLECTED view, forward cross left == down
5224                 // so our cross products above need to be adjusted for a left handed coordinate system
5225                 CrossProduct(forward, left, v);
5226                 if(DotProduct(v, up) < 0)
5227                 {
5228                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5229                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5230                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5231                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5232                 }
5233
5234                 // Leaving those out was a mistake, those were in the old code, and they
5235                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5236                 // I couldn't reproduce it after adding those normalizations. --blub
5237                 VectorNormalize(r_refdef.view.frustum[0].normal);
5238                 VectorNormalize(r_refdef.view.frustum[1].normal);
5239                 VectorNormalize(r_refdef.view.frustum[2].normal);
5240                 VectorNormalize(r_refdef.view.frustum[3].normal);
5241
5242                 // make the corners absolute
5243                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5244                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5245                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5246                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5247
5248                 // one more normal
5249                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5250
5251                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5252                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5253                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5254                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5255                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5256         }
5257         else
5258         {
5259                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5260                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5261                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5262                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5263                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5264                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5265                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5266                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5267                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5268                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5269         }
5270         r_refdef.view.numfrustumplanes = 5;
5271
5272         if (r_refdef.view.useclipplane)
5273         {
5274                 r_refdef.view.numfrustumplanes = 6;
5275                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5276         }
5277
5278         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5279                 PlaneClassify(r_refdef.view.frustum + i);
5280
5281         // LordHavoc: note to all quake engine coders, Quake had a special case
5282         // for 90 degrees which assumed a square view (wrong), so I removed it,
5283         // Quake2 has it disabled as well.
5284
5285         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5286         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5287         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5288         //PlaneClassify(&frustum[0]);
5289
5290         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5291         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5292         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5293         //PlaneClassify(&frustum[1]);
5294
5295         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5296         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5297         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5298         //PlaneClassify(&frustum[2]);
5299
5300         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5301         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5302         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5303         //PlaneClassify(&frustum[3]);
5304
5305         // nearclip plane
5306         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5307         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5308         //PlaneClassify(&frustum[4]);
5309 }
5310
5311 void R_View_UpdateWithScissor(const int *myscissor)
5312 {
5313         R_Main_ResizeViewCache();
5314         R_View_SetFrustum(myscissor);
5315         R_View_WorldVisibility(r_refdef.view.useclipplane);
5316         R_View_UpdateEntityVisible();
5317         R_View_UpdateEntityLighting();
5318         R_AnimCache_CacheVisibleEntities();
5319 }
5320
5321 void R_View_Update(void)
5322 {
5323         R_Main_ResizeViewCache();
5324         R_View_SetFrustum(NULL);
5325         R_View_WorldVisibility(r_refdef.view.useclipplane);
5326         R_View_UpdateEntityVisible();
5327         R_View_UpdateEntityLighting();
5328         R_AnimCache_CacheVisibleEntities();
5329 }
5330
5331 float viewscalefpsadjusted = 1.0f;
5332
5333 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5334 {
5335         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5336         scale = bound(0.03125f, scale, 1.0f);
5337         *outwidth = (int)ceil(width * scale);
5338         *outheight = (int)ceil(height * scale);
5339 }
5340
5341 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5342 {
5343         const float *customclipplane = NULL;
5344         float plane[4];
5345         int scaledwidth, scaledheight;
5346         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5347         {
5348                 // LordHavoc: couldn't figure out how to make this approach the
5349                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5350                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5351                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5352                         dist = r_refdef.view.clipplane.dist;
5353                 plane[0] = r_refdef.view.clipplane.normal[0];
5354                 plane[1] = r_refdef.view.clipplane.normal[1];
5355                 plane[2] = r_refdef.view.clipplane.normal[2];
5356                 plane[3] = -dist;
5357                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5358         }
5359
5360         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5361         if (!r_refdef.view.useperspective)
5362                 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);
5363         else if (vid.stencil && r_useinfinitefarclip.integer)
5364                 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);
5365         else
5366                 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);
5367         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5368         R_SetViewport(&r_refdef.view.viewport);
5369         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5370         {
5371                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5372                 float screenplane[4];
5373                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5374                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5375                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5376                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5377                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5378         }
5379 }
5380
5381 void R_EntityMatrix(const matrix4x4_t *matrix)
5382 {
5383         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5384         {
5385                 gl_modelmatrixchanged = false;
5386                 gl_modelmatrix = *matrix;
5387                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5388                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5389                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5390                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5391                 CHECKGLERROR
5392                 switch(vid.renderpath)
5393                 {
5394                 case RENDERPATH_D3D9:
5395 #ifdef SUPPORTD3D
5396                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5397                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5398 #endif
5399                         break;
5400                 case RENDERPATH_D3D10:
5401                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5402                         break;
5403                 case RENDERPATH_D3D11:
5404                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5405                         break;
5406                 case RENDERPATH_GL11:
5407                 case RENDERPATH_GL13:
5408                 case RENDERPATH_GLES1:
5409                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5410                         break;
5411                 case RENDERPATH_SOFT:
5412                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5413                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5414                         break;
5415                 case RENDERPATH_GL20:
5416                 case RENDERPATH_GLES2:
5417                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5418                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5419                         break;
5420                 }
5421         }
5422 }
5423
5424 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5425 {
5426         r_viewport_t viewport;
5427         DrawQ_Finish();
5428
5429         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5430         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);
5431         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5432         R_SetViewport(&viewport);
5433         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5434         GL_Color(1, 1, 1, 1);
5435         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5436         GL_BlendFunc(GL_ONE, GL_ZERO);
5437         GL_ScissorTest(false);
5438         GL_DepthMask(false);
5439         GL_DepthRange(0, 1);
5440         GL_DepthTest(false);
5441         GL_DepthFunc(GL_LEQUAL);
5442         R_EntityMatrix(&identitymatrix);
5443         R_Mesh_ResetTextureState();
5444         GL_PolygonOffset(0, 0);
5445         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5446         switch(vid.renderpath)
5447         {
5448         case RENDERPATH_GL11:
5449         case RENDERPATH_GL13:
5450         case RENDERPATH_GL20:
5451         case RENDERPATH_GLES1:
5452         case RENDERPATH_GLES2:
5453                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5454                 break;
5455         case RENDERPATH_D3D9:
5456         case RENDERPATH_D3D10:
5457         case RENDERPATH_D3D11:
5458         case RENDERPATH_SOFT:
5459                 break;
5460         }
5461         GL_CullFace(GL_NONE);
5462 }
5463
5464 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5465 {
5466         DrawQ_Finish();
5467
5468         R_SetupView(true, fbo, depthtexture, colortexture);
5469         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5470         GL_Color(1, 1, 1, 1);
5471         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5472         GL_BlendFunc(GL_ONE, GL_ZERO);
5473         GL_ScissorTest(true);
5474         GL_DepthMask(true);
5475         GL_DepthRange(0, 1);
5476         GL_DepthTest(true);
5477         GL_DepthFunc(GL_LEQUAL);
5478         R_EntityMatrix(&identitymatrix);
5479         R_Mesh_ResetTextureState();
5480         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5481         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5482         switch(vid.renderpath)
5483         {
5484         case RENDERPATH_GL11:
5485         case RENDERPATH_GL13:
5486         case RENDERPATH_GL20:
5487         case RENDERPATH_GLES1:
5488         case RENDERPATH_GLES2:
5489                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5490                 break;
5491         case RENDERPATH_D3D9:
5492         case RENDERPATH_D3D10:
5493         case RENDERPATH_D3D11:
5494         case RENDERPATH_SOFT:
5495                 break;
5496         }
5497         GL_CullFace(r_refdef.view.cullface_back);
5498 }
5499
5500 /*
5501 ================
5502 R_RenderView_UpdateViewVectors
5503 ================
5504 */
5505 static void R_RenderView_UpdateViewVectors(void)
5506 {
5507         // break apart the view matrix into vectors for various purposes
5508         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5509         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5510         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5511         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5512         // make an inverted copy of the view matrix for tracking sprites
5513         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5514 }
5515
5516 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5517 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5518
5519 static void R_Water_StartFrame(void)
5520 {
5521         int i;
5522         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5523         r_waterstate_waterplane_t *p;
5524
5525         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5526                 return;
5527
5528         switch(vid.renderpath)
5529         {
5530         case RENDERPATH_GL20:
5531         case RENDERPATH_D3D9:
5532         case RENDERPATH_D3D10:
5533         case RENDERPATH_D3D11:
5534         case RENDERPATH_SOFT:
5535         case RENDERPATH_GLES2:
5536                 break;
5537         case RENDERPATH_GL11:
5538         case RENDERPATH_GL13:
5539         case RENDERPATH_GLES1:
5540                 return;
5541         }
5542
5543         // set waterwidth and waterheight to the water resolution that will be
5544         // used (often less than the screen resolution for faster rendering)
5545         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5546
5547         // calculate desired texture sizes
5548         // can't use water if the card does not support the texture size
5549         if (!r_water.integer || r_showsurfaces.integer)
5550                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5551         else if (vid.support.arb_texture_non_power_of_two)
5552         {
5553                 texturewidth = waterwidth;
5554                 textureheight = waterheight;
5555                 camerawidth = waterwidth;
5556                 cameraheight = waterheight;
5557         }
5558         else
5559         {
5560                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5561                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5562                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5563                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5564         }
5565
5566         // allocate textures as needed
5567         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight)
5568         {
5569                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5570                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5571                 {
5572                         if (p->texture_refraction)
5573                                 R_FreeTexture(p->texture_refraction);
5574                         p->texture_refraction = NULL;
5575                         if (p->texture_reflection)
5576                                 R_FreeTexture(p->texture_reflection);
5577                         p->texture_reflection = NULL;
5578                         if (p->texture_camera)
5579                                 R_FreeTexture(p->texture_camera);
5580                         p->texture_camera = NULL;
5581                 }
5582                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5583                 r_fb.water.texturewidth = texturewidth;
5584                 r_fb.water.textureheight = textureheight;
5585                 r_fb.water.camerawidth = camerawidth;
5586                 r_fb.water.cameraheight = cameraheight;
5587         }
5588
5589         if (r_fb.water.texturewidth)
5590         {
5591                 int scaledwidth, scaledheight;
5592
5593                 r_fb.water.enabled = true;
5594
5595                 // water resolution is usually reduced
5596                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5597                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5598                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5599
5600                 // set up variables that will be used in shader setup
5601                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5602                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5603                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5604                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5605         }
5606
5607         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5608         r_fb.water.numwaterplanes = 0;
5609 }
5610
5611 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5612 {
5613         int planeindex, bestplaneindex, vertexindex;
5614         vec3_t mins, maxs, normal, center, v, n;
5615         vec_t planescore, bestplanescore;
5616         mplane_t plane;
5617         r_waterstate_waterplane_t *p;
5618         texture_t *t = R_GetCurrentTexture(surface->texture);
5619
5620         rsurface.texture = t;
5621         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5622         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5623         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5624                 return;
5625         // average the vertex normals, find the surface bounds (after deformvertexes)
5626         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5627         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5628         VectorCopy(n, normal);
5629         VectorCopy(v, mins);
5630         VectorCopy(v, maxs);
5631         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5632         {
5633                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5634                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5635                 VectorAdd(normal, n, normal);
5636                 mins[0] = min(mins[0], v[0]);
5637                 mins[1] = min(mins[1], v[1]);
5638                 mins[2] = min(mins[2], v[2]);
5639                 maxs[0] = max(maxs[0], v[0]);
5640                 maxs[1] = max(maxs[1], v[1]);
5641                 maxs[2] = max(maxs[2], v[2]);
5642         }
5643         VectorNormalize(normal);
5644         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5645
5646         VectorCopy(normal, plane.normal);
5647         VectorNormalize(plane.normal);
5648         plane.dist = DotProduct(center, plane.normal);
5649         PlaneClassify(&plane);
5650         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5651         {
5652                 // skip backfaces (except if nocullface is set)
5653 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5654 //                      return;
5655                 VectorNegate(plane.normal, plane.normal);
5656                 plane.dist *= -1;
5657                 PlaneClassify(&plane);
5658         }
5659
5660
5661         // find a matching plane if there is one
5662         bestplaneindex = -1;
5663         bestplanescore = 1048576.0f;
5664         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5665         {
5666                 if(p->camera_entity == t->camera_entity)
5667                 {
5668                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5669                         if (bestplaneindex < 0 || bestplanescore > planescore)
5670                         {
5671                                 bestplaneindex = planeindex;
5672                                 bestplanescore = planescore;
5673                         }
5674                 }
5675         }
5676         planeindex = bestplaneindex;
5677         p = r_fb.water.waterplanes + planeindex;
5678
5679         // if this surface does not fit any known plane rendered this frame, add one
5680         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5681         {
5682                 // store the new plane
5683                 planeindex = r_fb.water.numwaterplanes++;
5684                 p = r_fb.water.waterplanes + planeindex;
5685                 p->plane = plane;
5686                 // clear materialflags and pvs
5687                 p->materialflags = 0;
5688                 p->pvsvalid = false;
5689                 p->camera_entity = t->camera_entity;
5690                 VectorCopy(mins, p->mins);
5691                 VectorCopy(maxs, p->maxs);
5692         }
5693         else
5694         {
5695                 // merge mins/maxs when we're adding this surface to the plane
5696                 p->mins[0] = min(p->mins[0], mins[0]);
5697                 p->mins[1] = min(p->mins[1], mins[1]);
5698                 p->mins[2] = min(p->mins[2], mins[2]);
5699                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5700                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5701                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5702         }
5703         // merge this surface's materialflags into the waterplane
5704         p->materialflags |= t->currentmaterialflags;
5705         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5706         {
5707                 // merge this surface's PVS into the waterplane
5708                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5709                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5710                 {
5711                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5712                         p->pvsvalid = true;
5713                 }
5714         }
5715 }
5716
5717 extern cvar_t r_drawparticles;
5718 extern cvar_t r_drawdecals;
5719
5720 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5721 {
5722         int myscissor[4];
5723         r_refdef_view_t originalview;
5724         r_refdef_view_t myview;
5725         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;
5726         r_waterstate_waterplane_t *p;
5727         vec3_t visorigin;
5728
5729         originalview = r_refdef.view;
5730
5731         // lowquality hack, temporarily shut down some cvars and restore afterwards
5732         qualityreduction = r_water_lowquality.integer;
5733         if (qualityreduction > 0)
5734         {
5735                 if (qualityreduction >= 1)
5736                 {
5737                         old_r_shadows = r_shadows.integer;
5738                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5739                         old_r_dlight = r_shadow_realtime_dlight.integer;
5740                         Cvar_SetValueQuick(&r_shadows, 0);
5741                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5742                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5743                 }
5744                 if (qualityreduction >= 2)
5745                 {
5746                         old_r_dynamic = r_dynamic.integer;
5747                         old_r_particles = r_drawparticles.integer;
5748                         old_r_decals = r_drawdecals.integer;
5749                         Cvar_SetValueQuick(&r_dynamic, 0);
5750                         Cvar_SetValueQuick(&r_drawparticles, 0);
5751                         Cvar_SetValueQuick(&r_drawdecals, 0);
5752                 }
5753         }
5754
5755         // make sure enough textures are allocated
5756         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5757         {
5758                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5759                 {
5760                         if (!p->texture_refraction)
5761                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5762                         if (!p->texture_refraction)
5763                                 goto error;
5764                 }
5765                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5766                 {
5767                         if (!p->texture_camera)
5768                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5769                         if (!p->texture_camera)
5770                                 goto error;
5771                 }
5772
5773                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5774                 {
5775                         if (!p->texture_reflection)
5776                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5777                         if (!p->texture_reflection)
5778                                 goto error;
5779                 }
5780         }
5781
5782         // render views
5783         r_refdef.view = originalview;
5784         r_refdef.view.showdebug = false;
5785         r_refdef.view.width = r_fb.water.waterwidth;
5786         r_refdef.view.height = r_fb.water.waterheight;
5787         r_refdef.view.useclipplane = true;
5788         myview = r_refdef.view;
5789         r_fb.water.renderingscene = true;
5790         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5791         {
5792                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5793                 {
5794                         r_refdef.view = myview;
5795                         if(r_water_scissormode.integer)
5796                         {
5797                                 R_SetupView(true, fbo, depthtexture, colortexture);
5798                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5799                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5800                         }
5801
5802                         // render reflected scene and copy into texture
5803                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5804                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5805                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5806                         r_refdef.view.clipplane = p->plane;
5807                         // reverse the cullface settings for this render
5808                         r_refdef.view.cullface_front = GL_FRONT;
5809                         r_refdef.view.cullface_back = GL_BACK;
5810                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5811                         {
5812                                 r_refdef.view.usecustompvs = true;
5813                                 if (p->pvsvalid)
5814                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5815                                 else
5816                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5817                         }
5818
5819                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5820                         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5821                         R_ClearScreen(r_refdef.fogenabled);
5822                         if(r_water_scissormode.integer & 2)
5823                                 R_View_UpdateWithScissor(myscissor);
5824                         else
5825                                 R_View_Update();
5826                         if(r_water_scissormode.integer & 1)
5827                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5828                         R_RenderScene(fbo, depthtexture, colortexture);
5829
5830                         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);
5831                         r_fb.water.hideplayer = false;
5832                 }
5833
5834                 // render the normal view scene and copy into texture
5835                 // (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)
5836                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5837                 {
5838                         r_refdef.view = myview;
5839                         if(r_water_scissormode.integer)
5840                         {
5841                                 R_SetupView(true, fbo, depthtexture, colortexture);
5842                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5843                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5844                         }
5845
5846                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5847
5848                         r_refdef.view.clipplane = p->plane;
5849                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5850                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5851
5852                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5853                         {
5854                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5855                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5856                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5857                                 R_RenderView_UpdateViewVectors();
5858                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5859                                 {
5860                                         r_refdef.view.usecustompvs = true;
5861                                         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);
5862                                 }
5863                         }
5864
5865                         PlaneClassify(&r_refdef.view.clipplane);
5866
5867                         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5868                         R_ClearScreen(r_refdef.fogenabled);
5869                         if(r_water_scissormode.integer & 2)
5870                                 R_View_UpdateWithScissor(myscissor);
5871                         else
5872                                 R_View_Update();
5873                         if(r_water_scissormode.integer & 1)
5874                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5875                         R_RenderScene(fbo, depthtexture, colortexture);
5876
5877                         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);
5878                         r_fb.water.hideplayer = false;
5879                 }
5880                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5881                 {
5882                         r_refdef.view = myview;
5883
5884                         r_refdef.view.clipplane = p->plane;
5885                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5886                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5887
5888                         r_refdef.view.width = r_fb.water.camerawidth;
5889                         r_refdef.view.height = r_fb.water.cameraheight;
5890                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5891                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5892                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5893                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5894
5895                         if(p->camera_entity)
5896                         {
5897                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5898                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5899                         }
5900
5901                         // note: all of the view is used for displaying... so
5902                         // there is no use in scissoring
5903
5904                         // reverse the cullface settings for this render
5905                         r_refdef.view.cullface_front = GL_FRONT;
5906                         r_refdef.view.cullface_back = GL_BACK;
5907                         // also reverse the view matrix
5908                         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
5909                         R_RenderView_UpdateViewVectors();
5910                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5911                         {
5912                                 r_refdef.view.usecustompvs = true;
5913                                 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);
5914                         }
5915                         
5916                         // camera needs no clipplane
5917                         r_refdef.view.useclipplane = false;
5918
5919                         PlaneClassify(&r_refdef.view.clipplane);
5920
5921                         r_fb.water.hideplayer = false;
5922
5923                         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5924                         R_ClearScreen(r_refdef.fogenabled);
5925                         R_View_Update();
5926                         R_RenderScene(fbo, depthtexture, colortexture);
5927
5928                         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);
5929                         r_fb.water.hideplayer = false;
5930                 }
5931
5932         }
5933         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5934         r_fb.water.renderingscene = false;
5935         r_refdef.view = originalview;
5936         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5937         R_ClearScreen(r_refdef.fogenabled);
5938         R_View_Update();
5939         goto finish;
5940 error:
5941         r_refdef.view = originalview;
5942         r_fb.water.renderingscene = false;
5943         Cvar_SetValueQuick(&r_water, 0);
5944         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5945 finish:
5946         // lowquality hack, restore cvars
5947         if (qualityreduction > 0)
5948         {
5949                 if (qualityreduction >= 1)
5950                 {
5951                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5952                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5953                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5954                 }
5955                 if (qualityreduction >= 2)
5956                 {
5957                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5958                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5959                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5960                 }
5961         }
5962 }
5963
5964 void R_Bloom_StartFrame(void)
5965 {
5966         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5967         int viewwidth, viewheight;
5968         textype_t textype;
5969
5970         if (r_viewscale_fpsscaling.integer)
5971         {
5972                 double actualframetime;
5973                 double targetframetime;
5974                 double adjust;
5975                 actualframetime = r_refdef.lastdrawscreentime;
5976                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5977                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5978                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5979                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5980                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5981                 viewscalefpsadjusted += adjust;
5982                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5983         }
5984         else
5985                 viewscalefpsadjusted = 1.0f;
5986
5987         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5988
5989         switch(vid.renderpath)
5990         {
5991         case RENDERPATH_GL20:
5992         case RENDERPATH_D3D9:
5993         case RENDERPATH_D3D10:
5994         case RENDERPATH_D3D11:
5995         case RENDERPATH_SOFT:
5996         case RENDERPATH_GLES2:
5997                 break;
5998         case RENDERPATH_GL11:
5999         case RENDERPATH_GL13:
6000         case RENDERPATH_GLES1:
6001                 return;
6002         }
6003
6004         // set bloomwidth and bloomheight to the bloom resolution that will be
6005         // used (often less than the screen resolution for faster rendering)
6006         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6007         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6008         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6009         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6010         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6011
6012         // calculate desired texture sizes
6013         if (vid.support.arb_texture_non_power_of_two)
6014         {
6015                 screentexturewidth = vid.width;
6016                 screentextureheight = vid.height;
6017                 bloomtexturewidth = r_fb.bloomwidth;
6018                 bloomtextureheight = r_fb.bloomheight;
6019         }
6020         else
6021         {
6022                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6023                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6024                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6025                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6026         }
6027
6028         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))
6029         {
6030                 Cvar_SetValueQuick(&r_hdr, 0);
6031                 Cvar_SetValueQuick(&r_bloom, 0);
6032                 Cvar_SetValueQuick(&r_motionblur, 0);
6033                 Cvar_SetValueQuick(&r_damageblur, 0);
6034         }
6035
6036         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)
6037                 screentexturewidth = screentextureheight = 0;
6038         if (!r_hdr.integer && !r_bloom.integer)
6039                 bloomtexturewidth = bloomtextureheight = 0;
6040
6041         textype = TEXTYPE_COLORBUFFER;
6042         switch (vid.renderpath)
6043         {
6044         case RENDERPATH_GL20:
6045         case RENDERPATH_GLES2:
6046                 if (vid.support.ext_framebuffer_object)
6047                 {
6048                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6049                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6050                 }
6051                 break;
6052         case RENDERPATH_GL11:
6053         case RENDERPATH_GL13:
6054         case RENDERPATH_GLES1:
6055         case RENDERPATH_D3D9:
6056         case RENDERPATH_D3D10:
6057         case RENDERPATH_D3D11:
6058         case RENDERPATH_SOFT:
6059                 break;
6060         }
6061
6062         // allocate textures as needed
6063         if (r_fb.screentexturewidth != screentexturewidth
6064          || r_fb.screentextureheight != screentextureheight
6065          || r_fb.bloomtexturewidth != bloomtexturewidth
6066          || r_fb.bloomtextureheight != bloomtextureheight
6067          || r_fb.texturetype != textype
6068          || r_fb.viewfbo != r_viewfbo.integer)
6069         {
6070                 if (r_fb.texture_bloom)
6071                         R_FreeTexture(r_fb.texture_bloom);
6072                 r_fb.texture_bloom = NULL;
6073                 if (r_fb.texture_screen)
6074                         R_FreeTexture(r_fb.texture_screen);
6075                 r_fb.texture_screen = NULL;
6076                 if (r_fb.fbo_framebuffer)
6077                         R_Mesh_DestroyFramebufferObject(r_fb.fbo_framebuffer);
6078                 r_fb.fbo_framebuffer = 0;
6079                 if (r_fb.texture_framebuffercolor)
6080                         R_FreeTexture(r_fb.texture_framebuffercolor);
6081                 r_fb.texture_framebuffercolor = NULL;
6082                 if (r_fb.texture_framebufferdepth)
6083                         R_FreeTexture(r_fb.texture_framebufferdepth);
6084                 r_fb.texture_framebufferdepth = NULL;
6085                 r_fb.screentexturewidth = screentexturewidth;
6086                 r_fb.screentextureheight = screentextureheight;
6087                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6088                         r_fb.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6089                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6090                 {
6091                         // FIXME: choose depth bits based on a cvar
6092                         r_fb.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6093                         r_fb.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6094                         r_fb.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
6095                         R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
6096 #ifndef USE_GLES2
6097                         // render depth into one texture and normalmap into the other
6098                         if (qglDrawBuffer)
6099                         {
6100                                 int status;
6101                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6102                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6103                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6104                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6105                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6106                         }
6107 #endif
6108                 }
6109                 r_fb.bloomtexturewidth = bloomtexturewidth;
6110                 r_fb.bloomtextureheight = bloomtextureheight;
6111                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6112                         r_fb.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6113                 r_fb.viewfbo = r_viewfbo.integer;
6114                 r_fb.texturetype = textype;
6115         }
6116
6117         // bloom texture is a different resolution
6118         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6119         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6120         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6121         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6122         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6123
6124         // set up a texcoord array for the full resolution screen image
6125         // (we have to keep this around to copy back during final render)
6126         r_fb.screentexcoord2f[0] = 0;
6127         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6128         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6129         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6130         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6131         r_fb.screentexcoord2f[5] = 0;
6132         r_fb.screentexcoord2f[6] = 0;
6133         r_fb.screentexcoord2f[7] = 0;
6134
6135         // set up a texcoord array for the reduced resolution bloom image
6136         // (which will be additive blended over the screen image)
6137         r_fb.bloomtexcoord2f[0] = 0;
6138         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6139         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6140         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6141         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6142         r_fb.bloomtexcoord2f[5] = 0;
6143         r_fb.bloomtexcoord2f[6] = 0;
6144         r_fb.bloomtexcoord2f[7] = 0;
6145
6146         switch(vid.renderpath)
6147         {
6148         case RENDERPATH_GL11:
6149         case RENDERPATH_GL13:
6150         case RENDERPATH_GL20:
6151         case RENDERPATH_SOFT:
6152         case RENDERPATH_GLES1:
6153         case RENDERPATH_GLES2:
6154                 break;
6155         case RENDERPATH_D3D9:
6156         case RENDERPATH_D3D10:
6157         case RENDERPATH_D3D11:
6158                 {
6159                         int i;
6160                         for (i = 0;i < 4;i++)
6161                         {
6162                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6163                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6164                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6165                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6166                         }
6167                 }
6168                 break;
6169         }
6170
6171         if ((r_hdr.integer || r_bloom.integer) && r_fb.bloomwidth)
6172         {
6173                 r_fb.enabled = true;
6174                 r_fb.hdr = r_hdr.integer != 0 && !r_fb.fbo_framebuffer;
6175         }
6176
6177         R_Viewport_InitOrtho(&r_fb.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6178
6179         if (r_fb.fbo_framebuffer)
6180                 r_refdef.view.clear = true;
6181 }
6182
6183 void R_Bloom_CopyBloomTexture(float colorscale)
6184 {
6185         r_refdef.stats.bloom++;
6186
6187         // scale down screen texture to the bloom texture size
6188         CHECKGLERROR
6189         R_Mesh_SetRenderTargets(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor, NULL, NULL, NULL);
6190         R_SetViewport(&r_fb.viewport);
6191         GL_BlendFunc(GL_ONE, GL_ZERO);
6192         GL_Color(colorscale, colorscale, colorscale, 1);
6193         // 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...
6194         switch(vid.renderpath)
6195         {
6196         case RENDERPATH_GL11:
6197         case RENDERPATH_GL13:
6198         case RENDERPATH_GL20:
6199         case RENDERPATH_GLES1:
6200         case RENDERPATH_GLES2:
6201         case RENDERPATH_SOFT:
6202                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6203                 break;
6204         case RENDERPATH_D3D9:
6205         case RENDERPATH_D3D10:
6206         case RENDERPATH_D3D11:
6207                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6208                 break;
6209         }
6210         // TODO: do boxfilter scale-down in shader?
6211         R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true);
6212         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6213         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6214
6215         // we now have a bloom image in the framebuffer
6216         // copy it into the bloom image texture for later processing
6217         R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6218         r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6219 }
6220
6221 void R_Bloom_CopyHDRTexture(void)
6222 {
6223         R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6224         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6225 }
6226
6227 void R_Bloom_MakeTexture(void)
6228 {
6229         int x, range, dir;
6230         float xoffset, yoffset, r, brighten;
6231
6232         r_refdef.stats.bloom++;
6233
6234         R_ResetViewRendering2D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6235
6236         // we have a bloom image in the framebuffer
6237         CHECKGLERROR
6238         R_SetViewport(&r_fb.viewport);
6239
6240         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6241         {
6242                 x *= 2;
6243                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6244                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6245                 GL_Color(r,r,r,1);
6246                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6247                 R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6248                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6249                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6250
6251                 // copy the vertically blurred bloom view to a texture
6252                 R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6253                 r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6254         }
6255
6256         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6257         brighten = r_bloom_brighten.value;
6258         if (r_fb.hdr)
6259                 brighten *= r_hdr_range.value;
6260         brighten = sqrt(brighten);
6261         if(range >= 1)
6262                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6263         R_SetupShader_Generic(r_fb.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6264
6265         for (dir = 0;dir < 2;dir++)
6266         {
6267                 // blend on at multiple vertical offsets to achieve a vertical blur
6268                 // TODO: do offset blends using GLSL
6269                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6270                 GL_BlendFunc(GL_ONE, GL_ZERO);
6271                 for (x = -range;x <= range;x++)
6272                 {
6273                         if (!dir){xoffset = 0;yoffset = x;}
6274                         else {xoffset = x;yoffset = 0;}
6275                         xoffset /= (float)r_fb.bloomtexturewidth;
6276                         yoffset /= (float)r_fb.bloomtextureheight;
6277                         // compute a texcoord array with the specified x and y offset
6278                         r_fb.offsettexcoord2f[0] = xoffset+0;
6279                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6280                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6281                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6282                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6283                         r_fb.offsettexcoord2f[5] = yoffset+0;
6284                         r_fb.offsettexcoord2f[6] = xoffset+0;
6285                         r_fb.offsettexcoord2f[7] = yoffset+0;
6286                         // this r value looks like a 'dot' particle, fading sharply to
6287                         // black at the edges
6288                         // (probably not realistic but looks good enough)
6289                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6290                         //r = brighten/(range*2+1);
6291                         r = brighten / (range * 2 + 1);
6292                         if(range >= 1)
6293                                 r *= (1 - x*x/(float)(range*range));
6294                         GL_Color(r, r, r, 1);
6295                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6296                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6297                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6298                         GL_BlendFunc(GL_ONE, GL_ONE);
6299                 }
6300
6301                 // copy the vertically blurred bloom view to a texture
6302                 R_Mesh_CopyToTexture(r_fb.texture_bloom, 0, 0, r_fb.viewport.x, r_fb.viewport.y, r_fb.viewport.width, r_fb.viewport.height);
6303                 r_refdef.stats.bloom_copypixels += r_fb.viewport.width * r_fb.viewport.height;
6304         }
6305 }
6306
6307 void R_HDR_RenderBloomTexture(void)
6308 {
6309         int oldwidth, oldheight;
6310         float oldcolorscale;
6311         qboolean oldwaterstate;
6312
6313         oldwaterstate = r_fb.water.enabled;
6314         oldcolorscale = r_refdef.view.colorscale;
6315         oldwidth = r_refdef.view.width;
6316         oldheight = r_refdef.view.height;
6317         r_refdef.view.width = r_fb.bloomwidth;
6318         r_refdef.view.height = r_fb.bloomheight;
6319
6320         if(r_hdr.integer < 2)
6321                 r_fb.water.enabled = false;
6322
6323         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6324         // TODO: add exposure compensation features
6325         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6326
6327         r_refdef.view.showdebug = false;
6328         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6329
6330         R_ResetViewRendering3D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6331
6332         R_ClearScreen(r_refdef.fogenabled);
6333         if (r_timereport_active)
6334                 R_TimeReport("HDRclear");
6335
6336         R_View_Update();
6337         if (r_timereport_active)
6338                 R_TimeReport("visibility");
6339
6340         // only do secondary renders with HDR if r_hdr is 2 or higher
6341         r_fb.water.numwaterplanes = 0;
6342         if (r_fb.water.enabled)
6343                 R_RenderWaterPlanes(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6344
6345         r_refdef.view.showdebug = true;
6346         R_RenderScene(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6347         r_fb.water.numwaterplanes = 0;
6348
6349         R_ResetViewRendering2D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6350
6351         R_Bloom_CopyHDRTexture();
6352         R_Bloom_MakeTexture();
6353
6354         // restore the view settings
6355         r_fb.water.enabled = oldwaterstate;
6356         r_refdef.view.width = oldwidth;
6357         r_refdef.view.height = oldheight;
6358         r_refdef.view.colorscale = oldcolorscale;
6359
6360         R_ResetViewRendering3D(r_fb.fbo_framebuffer, r_fb.texture_framebufferdepth, r_fb.texture_framebuffercolor);
6361
6362         R_ClearScreen(r_refdef.fogenabled);
6363         if (r_timereport_active)
6364                 R_TimeReport("viewclear");
6365 }
6366
6367 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6368 {
6369         unsigned int permutation;
6370         float uservecs[4][4];
6371
6372         switch (vid.renderpath)
6373         {
6374         case RENDERPATH_GL20:
6375         case RENDERPATH_D3D9:
6376         case RENDERPATH_D3D10:
6377         case RENDERPATH_D3D11:
6378         case RENDERPATH_SOFT:
6379         case RENDERPATH_GLES2:
6380                 permutation =
6381                           (r_fb.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6382                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6383                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6384                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6385                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6386
6387                 if (r_fb.texture_screen)
6388                 {
6389                         // make sure the buffer is available
6390                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6391
6392                         R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6393
6394                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6395                         {
6396                                 // declare variables
6397                                 float blur_factor, blur_mouseaccel, blur_velocity;
6398                                 static float blur_average; 
6399                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6400
6401                                 // set a goal for the factoring
6402                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6403                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6404                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6405                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6406                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6407                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6408
6409                                 // from the goal, pick an averaged value between goal and last value
6410                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6411                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6412                                 
6413                                 // enforce minimum amount of blur 
6414                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6415                                 
6416                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6417
6418                                 // calculate values into a standard alpha
6419                                 cl.motionbluralpha = 1 - exp(-
6420                                                 (
6421                                                  (r_motionblur.value * blur_factor / 80)
6422                                                  +
6423                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6424                                                 )
6425                                                 /
6426                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6427                                           );
6428                                 
6429                                 // randomization for the blur value to combat persistent ghosting
6430                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6431                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6432                                 
6433                                 // apply the blur
6434                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6435                                 {
6436                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6437                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6438                                         switch(vid.renderpath)
6439                                         {
6440                                         case RENDERPATH_GL11:
6441                                         case RENDERPATH_GL13:
6442                                         case RENDERPATH_GL20:
6443                                         case RENDERPATH_GLES1:
6444                                         case RENDERPATH_GLES2:
6445                                         case RENDERPATH_SOFT:
6446                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6447                                                 break;
6448                                         case RENDERPATH_D3D9:
6449                                         case RENDERPATH_D3D10:
6450                                         case RENDERPATH_D3D11:
6451                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6452                                                 break;
6453                                         }
6454                                         R_SetupShader_Generic(r_fb.texture_screen, NULL, GL_MODULATE, 1, false, true);
6455                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6456                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6457                                 }
6458                                 
6459                                 // updates old view angles for next pass 
6460                                 VectorCopy(cl.viewangles, blur_oldangles);
6461                         }
6462
6463                         // copy view into the screen texture
6464                         R_Mesh_CopyToTexture(r_fb.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6465                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6466                 }
6467                 else
6468                 {
6469                         // we may still have to do view tint...
6470                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6471                         {
6472                                 // apply a color tint to the whole view
6473                                 R_ResetViewRendering2D(0, NULL, NULL);
6474                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6475                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6476                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6477                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6478                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6479                         }
6480                         break; // no screen processing, no bloom, skip it
6481                 }
6482
6483                 if (r_fb.texture_bloom && !r_fb.hdr)
6484                 {
6485                         // render simple bloom effect
6486                         // copy the screen and shrink it and darken it for the bloom process
6487                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6488                         // make the bloom texture
6489                         R_Bloom_MakeTexture();
6490                 }
6491
6492 #if _MSC_VER >= 1400
6493 #define sscanf sscanf_s
6494 #endif
6495                 memset(uservecs, 0, sizeof(uservecs));
6496                 if (r_glsl_postprocess_uservec1_enable.integer)
6497                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6498                 if (r_glsl_postprocess_uservec2_enable.integer)
6499                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6500                 if (r_glsl_postprocess_uservec3_enable.integer)
6501                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6502                 if (r_glsl_postprocess_uservec4_enable.integer)
6503                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6504
6505                 R_ResetViewRendering2D(0, NULL, NULL);
6506                 GL_Color(1, 1, 1, 1);
6507                 GL_BlendFunc(GL_ONE, GL_ZERO);
6508
6509                 switch(vid.renderpath)
6510                 {
6511                 case RENDERPATH_GL20:
6512                 case RENDERPATH_GLES2:
6513                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6514                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6515                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.texture_screen);
6516                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.texture_bloom );
6517                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6518                         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]);
6519                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6520                         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]);
6521                         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]);
6522                         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]);
6523                         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]);
6524                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6525                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6526                         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);
6527                         break;
6528                 case RENDERPATH_D3D9:
6529 #ifdef SUPPORTD3D
6530                         // 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...
6531                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6532                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6533                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.texture_screen);
6534                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.texture_bloom );
6535                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6536                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6537                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6538                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6539                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6540                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6541                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6542                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6543                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6544                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6545 #endif
6546                         break;
6547                 case RENDERPATH_D3D10:
6548                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6549                         break;
6550                 case RENDERPATH_D3D11:
6551                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6552                         break;
6553                 case RENDERPATH_SOFT:
6554                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6555                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6556                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.texture_screen);
6557                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.texture_bloom );
6558                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6559                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6560                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6561                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6562                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6563                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6564                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6565                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6566                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6567                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6568                         break;
6569                 default:
6570                         break;
6571                 }
6572                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6573                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6574                 break;
6575         case RENDERPATH_GL11:
6576         case RENDERPATH_GL13:
6577         case RENDERPATH_GLES1:
6578                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6579                 {
6580                         // apply a color tint to the whole view
6581                         R_ResetViewRendering2D(0, NULL, NULL);
6582                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6583                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6584                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6585                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6586                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6587                 }
6588                 break;
6589         }
6590 }
6591
6592 matrix4x4_t r_waterscrollmatrix;
6593
6594 void R_UpdateFog(void)
6595 {
6596         // Nehahra fog
6597         if (gamemode == GAME_NEHAHRA)
6598         {
6599                 if (gl_fogenable.integer)
6600                 {
6601                         r_refdef.oldgl_fogenable = true;
6602                         r_refdef.fog_density = gl_fogdensity.value;
6603                         r_refdef.fog_red = gl_fogred.value;
6604                         r_refdef.fog_green = gl_foggreen.value;
6605                         r_refdef.fog_blue = gl_fogblue.value;
6606                         r_refdef.fog_alpha = 1;
6607                         r_refdef.fog_start = 0;
6608                         r_refdef.fog_end = gl_skyclip.value;
6609                         r_refdef.fog_height = 1<<30;
6610                         r_refdef.fog_fadedepth = 128;
6611                 }
6612                 else if (r_refdef.oldgl_fogenable)
6613                 {
6614                         r_refdef.oldgl_fogenable = false;
6615                         r_refdef.fog_density = 0;
6616                         r_refdef.fog_red = 0;
6617                         r_refdef.fog_green = 0;
6618                         r_refdef.fog_blue = 0;
6619                         r_refdef.fog_alpha = 0;
6620                         r_refdef.fog_start = 0;
6621                         r_refdef.fog_end = 0;
6622                         r_refdef.fog_height = 1<<30;
6623                         r_refdef.fog_fadedepth = 128;
6624                 }
6625         }
6626
6627         // fog parms
6628         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6629         r_refdef.fog_start = max(0, r_refdef.fog_start);
6630         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6631
6632         if (r_refdef.fog_density && r_drawfog.integer)
6633         {
6634                 r_refdef.fogenabled = true;
6635                 // this is the point where the fog reaches 0.9986 alpha, which we
6636                 // consider a good enough cutoff point for the texture
6637                 // (0.9986 * 256 == 255.6)
6638                 if (r_fog_exp2.integer)
6639                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6640                 else
6641                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6642                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6643                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6644                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6645                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6646                         R_BuildFogHeightTexture();
6647                 // fog color was already set
6648                 // update the fog texture
6649                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6650                         R_BuildFogTexture();
6651                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6652                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6653         }
6654         else
6655                 r_refdef.fogenabled = false;
6656
6657         // fog color
6658         if (r_refdef.fog_density)
6659         {
6660                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6661                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6662                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6663
6664                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6665                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6666                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6667                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6668
6669                 {
6670                         vec3_t fogvec;
6671                         VectorCopy(r_refdef.fogcolor, fogvec);
6672                         //   color.rgb *= ContrastBoost * SceneBrightness;
6673                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6674                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6675                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6676                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6677                 }
6678         }
6679 }
6680
6681 void R_UpdateVariables(void)
6682 {
6683         R_Textures_Frame();
6684
6685         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6686
6687         r_refdef.farclip = r_farclip_base.value;
6688         if (r_refdef.scene.worldmodel)
6689                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6690         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6691
6692         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6693                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6694         r_refdef.polygonfactor = 0;
6695         r_refdef.polygonoffset = 0;
6696         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6697         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6698
6699         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6700         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6701         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6702         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6703         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6704         if (FAKELIGHT_ENABLED)
6705         {
6706                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6707         }
6708         if (r_showsurfaces.integer)
6709         {
6710                 r_refdef.scene.rtworld = false;
6711                 r_refdef.scene.rtworldshadows = false;
6712                 r_refdef.scene.rtdlight = false;
6713                 r_refdef.scene.rtdlightshadows = false;
6714                 r_refdef.lightmapintensity = 0;
6715         }
6716
6717         switch(vid.renderpath)
6718         {
6719         case RENDERPATH_GL20:
6720         case RENDERPATH_D3D9:
6721         case RENDERPATH_D3D10:
6722         case RENDERPATH_D3D11:
6723         case RENDERPATH_SOFT:
6724         case RENDERPATH_GLES2:
6725                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6726                 {
6727                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6728                         {
6729                                 // build GLSL gamma texture
6730 #define RAMPWIDTH 256
6731                                 unsigned short ramp[RAMPWIDTH * 3];
6732                                 unsigned char rampbgr[RAMPWIDTH][4];
6733                                 int i;
6734
6735                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6736
6737                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6738                                 for(i = 0; i < RAMPWIDTH; ++i)
6739                                 {
6740                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6741                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6742                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6743                                         rampbgr[i][3] = 0;
6744                                 }
6745                                 if (r_texture_gammaramps)
6746                                 {
6747                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6748                                 }
6749                                 else
6750                                 {
6751                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6752                                 }
6753                         }
6754                 }
6755                 else
6756                 {
6757                         // remove GLSL gamma texture
6758                 }
6759                 break;
6760         case RENDERPATH_GL11:
6761         case RENDERPATH_GL13:
6762         case RENDERPATH_GLES1:
6763                 break;
6764         }
6765 }
6766
6767 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6768 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6769 /*
6770 ================
6771 R_SelectScene
6772 ================
6773 */
6774 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6775         if( scenetype != r_currentscenetype ) {
6776                 // store the old scenetype
6777                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6778                 r_currentscenetype = scenetype;
6779                 // move in the new scene
6780                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6781         }
6782 }
6783
6784 /*
6785 ================
6786 R_GetScenePointer
6787 ================
6788 */
6789 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6790 {
6791         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6792         if( scenetype == r_currentscenetype ) {
6793                 return &r_refdef.scene;
6794         } else {
6795                 return &r_scenes_store[ scenetype ];
6796         }
6797 }
6798
6799 int R_SortEntities_Compare(const void *ap, const void *bp)
6800 {
6801         const entity_render_t *a = *(const entity_render_t **)ap;
6802         const entity_render_t *b = *(const entity_render_t **)bp;
6803
6804         // 1. compare model
6805         if(a->model < b->model)
6806                 return -1;
6807         if(a->model > b->model)
6808                 return +1;
6809
6810         // 2. compare skin
6811         // TODO possibly calculate the REAL skinnum here first using
6812         // skinscenes?
6813         if(a->skinnum < b->skinnum)
6814                 return -1;
6815         if(a->skinnum > b->skinnum)
6816                 return +1;
6817
6818         // everything we compared is equal
6819         return 0;
6820 }
6821 void R_SortEntities(void)
6822 {
6823         // below or equal 2 ents, sorting never gains anything
6824         if(r_refdef.scene.numentities <= 2)
6825                 return;
6826         // sort
6827         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6828 }
6829
6830 /*
6831 ================
6832 R_RenderView
6833 ================
6834 */
6835 int dpsoftrast_test;
6836 extern void R_Shadow_UpdateBounceGridTexture(void);
6837 extern cvar_t r_shadow_bouncegrid;
6838 void R_RenderView(void)
6839 {
6840         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6841         int fbo;
6842         rtexture_t *depthtexture;
6843         rtexture_t *colortexture;
6844
6845         dpsoftrast_test = r_test.integer;
6846
6847         if (r_timereport_active)
6848                 R_TimeReport("start");
6849         r_textureframe++; // used only by R_GetCurrentTexture
6850         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6851
6852         if(R_CompileShader_CheckStaticParms())
6853                 R_GLSL_Restart_f();
6854
6855         if (!r_drawentities.integer)
6856                 r_refdef.scene.numentities = 0;
6857         else if (r_sortentities.integer)
6858                 R_SortEntities();
6859
6860         R_AnimCache_ClearCache();
6861         R_FrameData_NewFrame();
6862
6863         /* adjust for stereo display */
6864         if(R_Stereo_Active())
6865         {
6866                 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);
6867                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6868         }
6869
6870         if (r_refdef.view.isoverlay)
6871         {
6872                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6873                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6874                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6875                 R_TimeReport("depthclear");
6876
6877                 r_refdef.view.showdebug = false;
6878
6879                 r_fb.water.enabled = false;
6880                 r_fb.water.numwaterplanes = 0;
6881
6882                 R_RenderScene(0, NULL, NULL);
6883
6884                 r_refdef.view.matrix = originalmatrix;
6885
6886                 CHECKGLERROR
6887                 return;
6888         }
6889
6890         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6891         {
6892                 r_refdef.view.matrix = originalmatrix;
6893                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6894         }
6895
6896         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6897
6898         R_RenderView_UpdateViewVectors();
6899
6900         R_Shadow_UpdateWorldLightSelection();
6901
6902         R_Bloom_StartFrame();
6903         R_Water_StartFrame();
6904
6905         // now we probably have an fbo to render into
6906         fbo = r_fb.fbo_framebuffer;
6907         depthtexture = r_fb.texture_framebufferdepth;
6908         colortexture = r_fb.texture_framebuffercolor;
6909
6910         CHECKGLERROR
6911         if (r_timereport_active)
6912                 R_TimeReport("viewsetup");
6913
6914         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6915
6916         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6917         {
6918                 R_ClearScreen(r_refdef.fogenabled);
6919                 if (r_timereport_active)
6920                         R_TimeReport("viewclear");
6921         }
6922         r_refdef.view.clear = true;
6923
6924         // this produces a bloom texture to be used in R_BlendView() later
6925         if (r_fb.hdr)
6926         {
6927                 R_HDR_RenderBloomTexture();
6928                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6929                 r_textureframe++; // used only by R_GetCurrentTexture
6930         }
6931
6932         r_refdef.view.showdebug = true;
6933
6934         R_View_Update();
6935         if (r_timereport_active)
6936                 R_TimeReport("visibility");
6937
6938         R_Shadow_UpdateBounceGridTexture();
6939         if (r_timereport_active && r_shadow_bouncegrid.integer)
6940                 R_TimeReport("bouncegrid");
6941
6942         r_fb.water.numwaterplanes = 0;
6943         if (r_fb.water.enabled)
6944                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6945
6946         R_RenderScene(fbo, depthtexture, colortexture);
6947         r_fb.water.numwaterplanes = 0;
6948
6949         R_BlendView(fbo, depthtexture, colortexture);
6950         if (r_timereport_active)
6951                 R_TimeReport("blendview");
6952
6953         GL_Scissor(0, 0, vid.width, vid.height);
6954         GL_ScissorTest(false);
6955
6956         r_refdef.view.matrix = originalmatrix;
6957
6958         CHECKGLERROR
6959 }
6960
6961 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6962 {
6963         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6964         {
6965                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6966                 if (r_timereport_active)
6967                         R_TimeReport("waterworld");
6968         }
6969
6970         // don't let sound skip if going slow
6971         if (r_refdef.scene.extraupdate)
6972                 S_ExtraUpdate ();
6973
6974         R_DrawModelsAddWaterPlanes();
6975         if (r_timereport_active)
6976                 R_TimeReport("watermodels");
6977
6978         if (r_fb.water.numwaterplanes)
6979         {
6980                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6981                 if (r_timereport_active)
6982                         R_TimeReport("waterscenes");
6983         }
6984 }
6985
6986 extern void R_DrawLightningBeams (void);
6987 extern void VM_CL_AddPolygonsToMeshQueue (void);
6988 extern void R_DrawPortals (void);
6989 extern cvar_t cl_locs_show;
6990 static void R_DrawLocs(void);
6991 static void R_DrawEntityBBoxes(void);
6992 static void R_DrawModelDecals(void);
6993 extern void R_DrawModelShadows(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6994 extern void R_DrawModelShadowMaps(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
6995 extern cvar_t cl_decals_newsystem;
6996 extern qboolean r_shadow_usingdeferredprepass;
6997 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6998 {
6999         qboolean shadowmapping = false;
7000
7001         if (r_timereport_active)
7002                 R_TimeReport("beginscene");
7003
7004         r_refdef.stats.renders++;
7005
7006         R_UpdateFog();
7007
7008         // don't let sound skip if going slow
7009         if (r_refdef.scene.extraupdate)
7010                 S_ExtraUpdate ();
7011
7012         R_MeshQueue_BeginScene();
7013
7014         R_SkyStartFrame();
7015
7016         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);
7017
7018         if (r_timereport_active)
7019                 R_TimeReport("skystartframe");
7020
7021         if (cl.csqc_vidvars.drawworld)
7022         {
7023                 // don't let sound skip if going slow
7024                 if (r_refdef.scene.extraupdate)
7025                         S_ExtraUpdate ();
7026
7027                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7028                 {
7029                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7030                         if (r_timereport_active)
7031                                 R_TimeReport("worldsky");
7032                 }
7033
7034                 if (R_DrawBrushModelsSky() && r_timereport_active)
7035                         R_TimeReport("bmodelsky");
7036
7037                 if (skyrendermasked && skyrenderlater)
7038                 {
7039                         // we have to force off the water clipping plane while rendering sky
7040                         R_SetupView(false, fbo, depthtexture, colortexture);
7041                         R_Sky();
7042                         R_SetupView(true, fbo, depthtexture, colortexture);
7043                         if (r_timereport_active)
7044                                 R_TimeReport("sky");
7045                 }
7046         }
7047
7048         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7049         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7050                 R_Shadow_PrepareModelShadows();
7051         if (r_timereport_active)
7052                 R_TimeReport("preparelights");
7053
7054         if (R_Shadow_ShadowMappingEnabled())
7055                 shadowmapping = true;
7056
7057         if (r_shadow_usingdeferredprepass)
7058                 R_Shadow_DrawPrepass();
7059
7060         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7061         {
7062                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7063                 if (r_timereport_active)
7064                         R_TimeReport("worlddepth");
7065         }
7066         if (r_depthfirst.integer >= 2)
7067         {
7068                 R_DrawModelsDepth();
7069                 if (r_timereport_active)
7070                         R_TimeReport("modeldepth");
7071         }
7072
7073         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7074         {
7075                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7076                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7077                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7078                 // don't let sound skip if going slow
7079                 if (r_refdef.scene.extraupdate)
7080                         S_ExtraUpdate ();
7081         }
7082
7083         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7084         {
7085                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7086                 if (r_timereport_active)
7087                         R_TimeReport("world");
7088         }
7089
7090         // don't let sound skip if going slow
7091         if (r_refdef.scene.extraupdate)
7092                 S_ExtraUpdate ();
7093
7094         R_DrawModels();
7095         if (r_timereport_active)
7096                 R_TimeReport("models");
7097
7098         // don't let sound skip if going slow
7099         if (r_refdef.scene.extraupdate)
7100                 S_ExtraUpdate ();
7101
7102         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7103         {
7104                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7105                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7106                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7107                 // don't let sound skip if going slow
7108                 if (r_refdef.scene.extraupdate)
7109                         S_ExtraUpdate ();
7110         }
7111
7112         if (!r_shadow_usingdeferredprepass)
7113         {
7114                 R_Shadow_DrawLights();
7115                 if (r_timereport_active)
7116                         R_TimeReport("rtlights");
7117         }
7118
7119         // don't let sound skip if going slow
7120         if (r_refdef.scene.extraupdate)
7121                 S_ExtraUpdate ();
7122
7123         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7124         {
7125                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7126                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7127                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7128                 // don't let sound skip if going slow
7129                 if (r_refdef.scene.extraupdate)
7130                         S_ExtraUpdate ();
7131         }
7132
7133         if (cl.csqc_vidvars.drawworld)
7134         {
7135                 if (cl_decals_newsystem.integer)
7136                 {
7137                         R_DrawModelDecals();
7138                         if (r_timereport_active)
7139                                 R_TimeReport("modeldecals");
7140                 }
7141                 else
7142                 {
7143                         R_DrawDecals();
7144                         if (r_timereport_active)
7145                                 R_TimeReport("decals");
7146                 }
7147
7148                 R_DrawParticles();
7149                 if (r_timereport_active)
7150                         R_TimeReport("particles");
7151
7152                 R_DrawExplosions();
7153                 if (r_timereport_active)
7154                         R_TimeReport("explosions");
7155
7156                 R_DrawLightningBeams();
7157                 if (r_timereport_active)
7158                         R_TimeReport("lightning");
7159         }
7160
7161         VM_CL_AddPolygonsToMeshQueue();
7162
7163         if (r_refdef.view.showdebug)
7164         {
7165                 if (cl_locs_show.integer)
7166                 {
7167                         R_DrawLocs();
7168                         if (r_timereport_active)
7169                                 R_TimeReport("showlocs");
7170                 }
7171
7172                 if (r_drawportals.integer)
7173                 {
7174                         R_DrawPortals();
7175                         if (r_timereport_active)
7176                                 R_TimeReport("portals");
7177                 }
7178
7179                 if (r_showbboxes.value > 0)
7180                 {
7181                         R_DrawEntityBBoxes();
7182                         if (r_timereport_active)
7183                                 R_TimeReport("bboxes");
7184                 }
7185         }
7186
7187         if (r_transparent.integer)
7188         {
7189                 R_MeshQueue_RenderTransparent();
7190                 if (r_timereport_active)
7191                         R_TimeReport("drawtrans");
7192         }
7193
7194         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))
7195         {
7196                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7197                 if (r_timereport_active)
7198                         R_TimeReport("worlddebug");
7199                 R_DrawModelsDebug();
7200                 if (r_timereport_active)
7201                         R_TimeReport("modeldebug");
7202         }
7203
7204         if (cl.csqc_vidvars.drawworld)
7205         {
7206                 R_Shadow_DrawCoronas();
7207                 if (r_timereport_active)
7208                         R_TimeReport("coronas");
7209         }
7210
7211 #if 0
7212         {
7213                 GL_DepthTest(false);
7214                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7215                 GL_Color(1, 1, 1, 1);
7216                 qglBegin(GL_POLYGON);
7217                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7218                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7219                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7220                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7221                 qglEnd();
7222                 qglBegin(GL_POLYGON);
7223                 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]);
7224                 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]);
7225                 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]);
7226                 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]);
7227                 qglEnd();
7228                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7229         }
7230 #endif
7231
7232         // don't let sound skip if going slow
7233         if (r_refdef.scene.extraupdate)
7234                 S_ExtraUpdate ();
7235
7236         R_ResetViewRendering2D(fbo, depthtexture, colortexture);
7237 }
7238
7239 static const unsigned short bboxelements[36] =
7240 {
7241         5, 1, 3, 5, 3, 7,
7242         6, 2, 0, 6, 0, 4,
7243         7, 3, 2, 7, 2, 6,
7244         4, 0, 1, 4, 1, 5,
7245         4, 5, 7, 4, 7, 6,
7246         1, 0, 2, 1, 2, 3,
7247 };
7248
7249 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7250 {
7251         int i;
7252         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7253
7254         RSurf_ActiveWorldEntity();
7255
7256         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7257         GL_DepthMask(false);
7258         GL_DepthRange(0, 1);
7259         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7260 //      R_Mesh_ResetTextureState();
7261
7262         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7263         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7264         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7265         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7266         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7267         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7268         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7269         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7270         R_FillColors(color4f, 8, cr, cg, cb, ca);
7271         if (r_refdef.fogenabled)
7272         {
7273                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7274                 {
7275                         f1 = RSurf_FogVertex(v);
7276                         f2 = 1 - f1;
7277                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7278                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7279                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7280                 }
7281         }
7282         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7283         R_Mesh_ResetTextureState();
7284         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7285         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7286 }
7287
7288 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7289 {
7290         int i;
7291         float color[4];
7292         prvm_edict_t *edict;
7293         prvm_prog_t *prog_save = prog;
7294
7295         // this function draws bounding boxes of server entities
7296         if (!sv.active)
7297                 return;
7298
7299         GL_CullFace(GL_NONE);
7300         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7301
7302         prog = 0;
7303         SV_VM_Begin();
7304         for (i = 0;i < numsurfaces;i++)
7305         {
7306                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7307                 switch ((int)PRVM_serveredictfloat(edict, solid))
7308                 {
7309                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7310                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7311                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7312                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7313                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7314                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7315                 }
7316                 color[3] *= r_showbboxes.value;
7317                 color[3] = bound(0, color[3], 1);
7318                 GL_DepthTest(!r_showdisabledepthtest.integer);
7319                 GL_CullFace(r_refdef.view.cullface_front);
7320                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7321         }
7322         SV_VM_End();
7323         prog = prog_save;
7324 }
7325
7326 static void R_DrawEntityBBoxes(void)
7327 {
7328         int i;
7329         prvm_edict_t *edict;
7330         vec3_t center;
7331         prvm_prog_t *prog_save = prog;
7332
7333         // this function draws bounding boxes of server entities
7334         if (!sv.active)
7335                 return;
7336
7337         prog = 0;
7338         SV_VM_Begin();
7339         for (i = 0;i < prog->num_edicts;i++)
7340         {
7341                 edict = PRVM_EDICT_NUM(i);
7342                 if (edict->priv.server->free)
7343                         continue;
7344                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7345                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7346                         continue;
7347                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7348                         continue;
7349                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7350                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7351         }
7352         SV_VM_End();
7353         prog = prog_save;
7354 }
7355
7356 static const int nomodelelement3i[24] =
7357 {
7358         5, 2, 0,
7359         5, 1, 2,
7360         5, 0, 3,
7361         5, 3, 1,
7362         0, 2, 4,
7363         2, 1, 4,
7364         3, 0, 4,
7365         1, 3, 4
7366 };
7367
7368 static const unsigned short nomodelelement3s[24] =
7369 {
7370         5, 2, 0,
7371         5, 1, 2,
7372         5, 0, 3,
7373         5, 3, 1,
7374         0, 2, 4,
7375         2, 1, 4,
7376         3, 0, 4,
7377         1, 3, 4
7378 };
7379
7380 static const float nomodelvertex3f[6*3] =
7381 {
7382         -16,   0,   0,
7383          16,   0,   0,
7384           0, -16,   0,
7385           0,  16,   0,
7386           0,   0, -16,
7387           0,   0,  16
7388 };
7389
7390 static const float nomodelcolor4f[6*4] =
7391 {
7392         0.0f, 0.0f, 0.5f, 1.0f,
7393         0.0f, 0.0f, 0.5f, 1.0f,
7394         0.0f, 0.5f, 0.0f, 1.0f,
7395         0.0f, 0.5f, 0.0f, 1.0f,
7396         0.5f, 0.0f, 0.0f, 1.0f,
7397         0.5f, 0.0f, 0.0f, 1.0f
7398 };
7399
7400 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7401 {
7402         int i;
7403         float f1, f2, *c;
7404         float color4f[6*4];
7405
7406         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);
7407
7408         // this is only called once per entity so numsurfaces is always 1, and
7409         // surfacelist is always {0}, so this code does not handle batches
7410
7411         if (rsurface.ent_flags & RENDER_ADDITIVE)
7412         {
7413                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7414                 GL_DepthMask(false);
7415         }
7416         else if (rsurface.colormod[3] < 1)
7417         {
7418                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7419                 GL_DepthMask(false);
7420         }
7421         else
7422         {
7423                 GL_BlendFunc(GL_ONE, GL_ZERO);
7424                 GL_DepthMask(true);
7425         }
7426         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7427         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7428         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7429         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7430         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7431         for (i = 0, c = color4f;i < 6;i++, c += 4)
7432         {
7433                 c[0] *= rsurface.colormod[0];
7434                 c[1] *= rsurface.colormod[1];
7435                 c[2] *= rsurface.colormod[2];
7436                 c[3] *= rsurface.colormod[3];
7437         }
7438         if (r_refdef.fogenabled)
7439         {
7440                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7441                 {
7442                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7443                         f2 = 1 - f1;
7444                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7445                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7446                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7447                 }
7448         }
7449 //      R_Mesh_ResetTextureState();
7450         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7451         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7452         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7453 }
7454
7455 void R_DrawNoModel(entity_render_t *ent)
7456 {
7457         vec3_t org;
7458         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7459         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7460                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7461         else
7462                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7463 }
7464
7465 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7466 {
7467         vec3_t right1, right2, diff, normal;
7468
7469         VectorSubtract (org2, org1, normal);
7470
7471         // calculate 'right' vector for start
7472         VectorSubtract (r_refdef.view.origin, org1, diff);
7473         CrossProduct (normal, diff, right1);
7474         VectorNormalize (right1);
7475
7476         // calculate 'right' vector for end
7477         VectorSubtract (r_refdef.view.origin, org2, diff);
7478         CrossProduct (normal, diff, right2);
7479         VectorNormalize (right2);
7480
7481         vert[ 0] = org1[0] + width * right1[0];
7482         vert[ 1] = org1[1] + width * right1[1];
7483         vert[ 2] = org1[2] + width * right1[2];
7484         vert[ 3] = org1[0] - width * right1[0];
7485         vert[ 4] = org1[1] - width * right1[1];
7486         vert[ 5] = org1[2] - width * right1[2];
7487         vert[ 6] = org2[0] - width * right2[0];
7488         vert[ 7] = org2[1] - width * right2[1];
7489         vert[ 8] = org2[2] - width * right2[2];
7490         vert[ 9] = org2[0] + width * right2[0];
7491         vert[10] = org2[1] + width * right2[1];
7492         vert[11] = org2[2] + width * right2[2];
7493 }
7494
7495 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)
7496 {
7497         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7498         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7499         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7500         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7501         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7502         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7503         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7504         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7505         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7506         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7507         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7508         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7509 }
7510
7511 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7512 {
7513         int i;
7514         float *vertex3f;
7515         float v[3];
7516         VectorSet(v, x, y, z);
7517         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7518                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7519                         break;
7520         if (i == mesh->numvertices)
7521         {
7522                 if (mesh->numvertices < mesh->maxvertices)
7523                 {
7524                         VectorCopy(v, vertex3f);
7525                         mesh->numvertices++;
7526                 }
7527                 return mesh->numvertices;
7528         }
7529         else
7530                 return i;
7531 }
7532
7533 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7534 {
7535         int i;
7536         int *e, element[3];
7537         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7538         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7539         e = mesh->element3i + mesh->numtriangles * 3;
7540         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7541         {
7542                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7543                 if (mesh->numtriangles < mesh->maxtriangles)
7544                 {
7545                         *e++ = element[0];
7546                         *e++ = element[1];
7547                         *e++ = element[2];
7548                         mesh->numtriangles++;
7549                 }
7550                 element[1] = element[2];
7551         }
7552 }
7553
7554 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7555 {
7556         int i;
7557         int *e, element[3];
7558         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7559         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7560         e = mesh->element3i + mesh->numtriangles * 3;
7561         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7562         {
7563                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7564                 if (mesh->numtriangles < mesh->maxtriangles)
7565                 {
7566                         *e++ = element[0];
7567                         *e++ = element[1];
7568                         *e++ = element[2];
7569                         mesh->numtriangles++;
7570                 }
7571                 element[1] = element[2];
7572         }
7573 }
7574
7575 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7576 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7577 {
7578         int planenum, planenum2;
7579         int w;
7580         int tempnumpoints;
7581         mplane_t *plane, *plane2;
7582         double maxdist;
7583         double temppoints[2][256*3];
7584         // figure out how large a bounding box we need to properly compute this brush
7585         maxdist = 0;
7586         for (w = 0;w < numplanes;w++)
7587                 maxdist = max(maxdist, fabs(planes[w].dist));
7588         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7589         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7590         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7591         {
7592                 w = 0;
7593                 tempnumpoints = 4;
7594                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7595                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7596                 {
7597                         if (planenum2 == planenum)
7598                                 continue;
7599                         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);
7600                         w = !w;
7601                 }
7602                 if (tempnumpoints < 3)
7603                         continue;
7604                 // generate elements forming a triangle fan for this polygon
7605                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7606         }
7607 }
7608
7609 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)
7610 {
7611         texturelayer_t *layer;
7612         layer = t->currentlayers + t->currentnumlayers++;
7613         layer->type = type;
7614         layer->depthmask = depthmask;
7615         layer->blendfunc1 = blendfunc1;
7616         layer->blendfunc2 = blendfunc2;
7617         layer->texture = texture;
7618         layer->texmatrix = *matrix;
7619         layer->color[0] = r;
7620         layer->color[1] = g;
7621         layer->color[2] = b;
7622         layer->color[3] = a;
7623 }
7624
7625 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7626 {
7627         if(parms[0] == 0 && parms[1] == 0)
7628                 return false;
7629         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7630                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7631                         return false;
7632         return true;
7633 }
7634
7635 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7636 {
7637         double index, f;
7638         index = parms[2] + rsurface.shadertime * parms[3];
7639         index -= floor(index);
7640         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7641         {
7642         default:
7643         case Q3WAVEFUNC_NONE:
7644         case Q3WAVEFUNC_NOISE:
7645         case Q3WAVEFUNC_COUNT:
7646                 f = 0;
7647                 break;
7648         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7649         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7650         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7651         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7652         case Q3WAVEFUNC_TRIANGLE:
7653                 index *= 4;
7654                 f = index - floor(index);
7655                 if (index < 1)
7656                 {
7657                         // f = f;
7658                 }
7659                 else if (index < 2)
7660                         f = 1 - f;
7661                 else if (index < 3)
7662                         f = -f;
7663                 else
7664                         f = -(1 - f);
7665                 break;
7666         }
7667         f = parms[0] + parms[1] * f;
7668         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7669                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7670         return (float) f;
7671 }
7672
7673 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7674 {
7675         int w, h, idx;
7676         double f;
7677         double offsetd[2];
7678         float tcmat[12];
7679         matrix4x4_t matrix, temp;
7680         switch(tcmod->tcmod)
7681         {
7682                 case Q3TCMOD_COUNT:
7683                 case Q3TCMOD_NONE:
7684                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7685                                 matrix = r_waterscrollmatrix;
7686                         else
7687                                 matrix = identitymatrix;
7688                         break;
7689                 case Q3TCMOD_ENTITYTRANSLATE:
7690                         // this is used in Q3 to allow the gamecode to control texcoord
7691                         // scrolling on the entity, which is not supported in darkplaces yet.
7692                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7693                         break;
7694                 case Q3TCMOD_ROTATE:
7695                         f = tcmod->parms[0] * rsurface.shadertime;
7696                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7697                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7698                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7699                         break;
7700                 case Q3TCMOD_SCALE:
7701                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7702                         break;
7703                 case Q3TCMOD_SCROLL:
7704                         // extra care is needed because of precision breakdown with large values of time
7705                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7706                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7707                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7708                         break;
7709                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7710                         w = (int) tcmod->parms[0];
7711                         h = (int) tcmod->parms[1];
7712                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7713                         f = f - floor(f);
7714                         idx = (int) floor(f * w * h);
7715                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7716                         break;
7717                 case Q3TCMOD_STRETCH:
7718                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7719                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7720                         break;
7721                 case Q3TCMOD_TRANSFORM:
7722                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7723                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7724                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7725                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7726                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7727                         break;
7728                 case Q3TCMOD_TURBULENT:
7729                         // this is handled in the RSurf_PrepareVertices function
7730                         matrix = identitymatrix;
7731                         break;
7732         }
7733         temp = *texmatrix;
7734         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7735 }
7736
7737 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7738 {
7739         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7740         char name[MAX_QPATH];
7741         skinframe_t *skinframe;
7742         unsigned char pixels[296*194];
7743         strlcpy(cache->name, skinname, sizeof(cache->name));
7744         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7745         if (developer_loading.integer)
7746                 Con_Printf("loading %s\n", name);
7747         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7748         if (!skinframe || !skinframe->base)
7749         {
7750                 unsigned char *f;
7751                 fs_offset_t filesize;
7752                 skinframe = NULL;
7753                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7754                 if (f)
7755                 {
7756                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7757                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7758                         Mem_Free(f);
7759                 }
7760         }
7761         cache->skinframe = skinframe;
7762 }
7763
7764 texture_t *R_GetCurrentTexture(texture_t *t)
7765 {
7766         int i;
7767         const entity_render_t *ent = rsurface.entity;
7768         dp_model_t *model = ent->model;
7769         q3shaderinfo_layer_tcmod_t *tcmod;
7770
7771         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7772                 return t->currentframe;
7773         t->update_lastrenderframe = r_textureframe;
7774         t->update_lastrenderentity = (void *)ent;
7775
7776         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7777                 t->camera_entity = ent->entitynumber;
7778         else
7779                 t->camera_entity = 0;
7780
7781         // switch to an alternate material if this is a q1bsp animated material
7782         {
7783                 texture_t *texture = t;
7784                 int s = rsurface.ent_skinnum;
7785                 if ((unsigned int)s >= (unsigned int)model->numskins)
7786                         s = 0;
7787                 if (model->skinscenes)
7788                 {
7789                         if (model->skinscenes[s].framecount > 1)
7790                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7791                         else
7792                                 s = model->skinscenes[s].firstframe;
7793                 }
7794                 if (s > 0)
7795                         t = t + s * model->num_surfaces;
7796                 if (t->animated)
7797                 {
7798                         // use an alternate animation if the entity's frame is not 0,
7799                         // and only if the texture has an alternate animation
7800                         if (rsurface.ent_alttextures && t->anim_total[1])
7801                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7802                         else
7803                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7804                 }
7805                 texture->currentframe = t;
7806         }
7807
7808         // update currentskinframe to be a qw skin or animation frame
7809         if (rsurface.ent_qwskin >= 0)
7810         {
7811                 i = rsurface.ent_qwskin;
7812                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7813                 {
7814                         r_qwskincache_size = cl.maxclients;
7815                         if (r_qwskincache)
7816                                 Mem_Free(r_qwskincache);
7817                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7818                 }
7819                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7820                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7821                 t->currentskinframe = r_qwskincache[i].skinframe;
7822                 if (t->currentskinframe == NULL)
7823                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7824         }
7825         else if (t->numskinframes >= 2)
7826                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7827         if (t->backgroundnumskinframes >= 2)
7828                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7829
7830         t->currentmaterialflags = t->basematerialflags;
7831         t->currentalpha = rsurface.colormod[3];
7832         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7833                 t->currentalpha *= r_wateralpha.value;
7834         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7835                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7836         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7837                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7838         if (!(rsurface.ent_flags & RENDER_LIGHT))
7839                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7840         else if (FAKELIGHT_ENABLED)
7841         {
7842                 // no modellight if using fakelight for the map
7843         }
7844         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7845         {
7846                 // pick a model lighting mode
7847                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7848                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7849                 else
7850                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7851         }
7852         if (rsurface.ent_flags & RENDER_ADDITIVE)
7853                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7854         else if (t->currentalpha < 1)
7855                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7856         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7857         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7858                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7859         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7860                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7861         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7862                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7863         if (t->backgroundnumskinframes)
7864                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7865         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7866         {
7867                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7868                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7869         }
7870         else
7871                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7872         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7873         {
7874                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7875                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7876         }
7877         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7878                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7879
7880         // there is no tcmod
7881         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7882         {
7883                 t->currenttexmatrix = r_waterscrollmatrix;
7884                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7885         }
7886         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7887         {
7888                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7889                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7890         }
7891
7892         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7893                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7894         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7895                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7896
7897         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7898         if (t->currentskinframe->qpixels)
7899                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7900         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7901         if (!t->basetexture)
7902                 t->basetexture = r_texture_notexture;
7903         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7904         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7905         t->nmaptexture = t->currentskinframe->nmap;
7906         if (!t->nmaptexture)
7907                 t->nmaptexture = r_texture_blanknormalmap;
7908         t->glosstexture = r_texture_black;
7909         t->glowtexture = t->currentskinframe->glow;
7910         t->fogtexture = t->currentskinframe->fog;
7911         t->reflectmasktexture = t->currentskinframe->reflect;
7912         if (t->backgroundnumskinframes)
7913         {
7914                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7915                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7916                 t->backgroundglosstexture = r_texture_black;
7917                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7918                 if (!t->backgroundnmaptexture)
7919                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7920         }
7921         else
7922         {
7923                 t->backgroundbasetexture = r_texture_white;
7924                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7925                 t->backgroundglosstexture = r_texture_black;
7926                 t->backgroundglowtexture = NULL;
7927         }
7928         t->specularpower = r_shadow_glossexponent.value;
7929         // TODO: store reference values for these in the texture?
7930         t->specularscale = 0;
7931         if (r_shadow_gloss.integer > 0)
7932         {
7933                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7934                 {
7935                         if (r_shadow_glossintensity.value > 0)
7936                         {
7937                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7938                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7939                                 t->specularscale = r_shadow_glossintensity.value;
7940                         }
7941                 }
7942                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7943                 {
7944                         t->glosstexture = r_texture_white;
7945                         t->backgroundglosstexture = r_texture_white;
7946                         t->specularscale = r_shadow_gloss2intensity.value;
7947                         t->specularpower = r_shadow_gloss2exponent.value;
7948                 }
7949         }
7950         t->specularscale *= t->specularscalemod;
7951         t->specularpower *= t->specularpowermod;
7952         t->rtlightambient = 0;
7953
7954         // lightmaps mode looks bad with dlights using actual texturing, so turn
7955         // off the colormap and glossmap, but leave the normalmap on as it still
7956         // accurately represents the shading involved
7957         if (gl_lightmaps.integer)
7958         {
7959                 t->basetexture = r_texture_grey128;
7960                 t->pantstexture = r_texture_black;
7961                 t->shirttexture = r_texture_black;
7962                 t->nmaptexture = r_texture_blanknormalmap;
7963                 t->glosstexture = r_texture_black;
7964                 t->glowtexture = NULL;
7965                 t->fogtexture = NULL;
7966                 t->reflectmasktexture = NULL;
7967                 t->backgroundbasetexture = NULL;
7968                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7969                 t->backgroundglosstexture = r_texture_black;
7970                 t->backgroundglowtexture = NULL;
7971                 t->specularscale = 0;
7972                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7973         }
7974
7975         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7976         VectorClear(t->dlightcolor);
7977         t->currentnumlayers = 0;
7978         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7979         {
7980                 int blendfunc1, blendfunc2;
7981                 qboolean depthmask;
7982                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7983                 {
7984                         blendfunc1 = GL_SRC_ALPHA;
7985                         blendfunc2 = GL_ONE;
7986                 }
7987                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7988                 {
7989                         blendfunc1 = GL_SRC_ALPHA;
7990                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7991                 }
7992                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7993                 {
7994                         blendfunc1 = t->customblendfunc[0];
7995                         blendfunc2 = t->customblendfunc[1];
7996                 }
7997                 else
7998                 {
7999                         blendfunc1 = GL_ONE;
8000                         blendfunc2 = GL_ZERO;
8001                 }
8002                 // don't colormod evilblend textures
8003                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8004                         VectorSet(t->lightmapcolor, 1, 1, 1);
8005                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8006                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8007                 {
8008                         // fullbright is not affected by r_refdef.lightmapintensity
8009                         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]);
8010                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8011                                 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]);
8012                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8013                                 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]);
8014                 }
8015                 else
8016                 {
8017                         vec3_t ambientcolor;
8018                         float colorscale;
8019                         // set the color tint used for lights affecting this surface
8020                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8021                         colorscale = 2;
8022                         // q3bsp has no lightmap updates, so the lightstylevalue that
8023                         // would normally be baked into the lightmap must be
8024                         // applied to the color
8025                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8026                         if (model->type == mod_brushq3)
8027                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8028                         colorscale *= r_refdef.lightmapintensity;
8029                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8030                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8031                         // basic lit geometry
8032                         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]);
8033                         // add pants/shirt if needed
8034                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8035                                 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]);
8036                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8037                                 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]);
8038                         // now add ambient passes if needed
8039                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8040                         {
8041                                 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]);
8042                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8043                                         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]);
8044                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8045                                         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]);
8046                         }
8047                 }
8048                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8049                         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]);
8050                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8051                 {
8052                         // if this is opaque use alpha blend which will darken the earlier
8053                         // passes cheaply.
8054                         //
8055                         // if this is an alpha blended material, all the earlier passes
8056                         // were darkened by fog already, so we only need to add the fog
8057                         // color ontop through the fog mask texture
8058                         //
8059                         // if this is an additive blended material, all the earlier passes
8060                         // were darkened by fog already, and we should not add fog color
8061                         // (because the background was not darkened, there is no fog color
8062                         // that was lost behind it).
8063                         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]);
8064                 }
8065         }
8066
8067         return t->currentframe;
8068 }
8069
8070 rsurfacestate_t rsurface;
8071
8072 void RSurf_ActiveWorldEntity(void)
8073 {
8074         dp_model_t *model = r_refdef.scene.worldmodel;
8075         //if (rsurface.entity == r_refdef.scene.worldentity)
8076         //      return;
8077         rsurface.entity = r_refdef.scene.worldentity;
8078         rsurface.skeleton = NULL;
8079         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8080         rsurface.ent_skinnum = 0;
8081         rsurface.ent_qwskin = -1;
8082         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8083         rsurface.shadertime = r_refdef.scene.time;
8084         rsurface.matrix = identitymatrix;
8085         rsurface.inversematrix = identitymatrix;
8086         rsurface.matrixscale = 1;
8087         rsurface.inversematrixscale = 1;
8088         R_EntityMatrix(&identitymatrix);
8089         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8090         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8091         rsurface.fograngerecip = r_refdef.fograngerecip;
8092         rsurface.fogheightfade = r_refdef.fogheightfade;
8093         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8094         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8095         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8096         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8097         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8098         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8099         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8100         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8101         rsurface.colormod[3] = 1;
8102         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);
8103         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8104         rsurface.frameblend[0].lerp = 1;
8105         rsurface.ent_alttextures = false;
8106         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8107         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8108         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8109         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8110         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8111         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8112         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8113         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8114         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8115         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8117         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8118         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8120         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8121         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8123         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8124         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8126         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8127         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8129         rsurface.modelelement3i = model->surfmesh.data_element3i;
8130         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8131         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8132         rsurface.modelelement3s = model->surfmesh.data_element3s;
8133         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8134         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8135         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8136         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8137         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8138         rsurface.modelsurfaces = model->data_surfaces;
8139         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8140         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8141         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8142         rsurface.modelgeneratedvertex = false;
8143         rsurface.batchgeneratedvertex = false;
8144         rsurface.batchfirstvertex = 0;
8145         rsurface.batchnumvertices = 0;
8146         rsurface.batchfirsttriangle = 0;
8147         rsurface.batchnumtriangles = 0;
8148         rsurface.batchvertex3f  = NULL;
8149         rsurface.batchvertex3f_vertexbuffer = NULL;
8150         rsurface.batchvertex3f_bufferoffset = 0;
8151         rsurface.batchsvector3f = NULL;
8152         rsurface.batchsvector3f_vertexbuffer = NULL;
8153         rsurface.batchsvector3f_bufferoffset = 0;
8154         rsurface.batchtvector3f = NULL;
8155         rsurface.batchtvector3f_vertexbuffer = NULL;
8156         rsurface.batchtvector3f_bufferoffset = 0;
8157         rsurface.batchnormal3f  = NULL;
8158         rsurface.batchnormal3f_vertexbuffer = NULL;
8159         rsurface.batchnormal3f_bufferoffset = 0;
8160         rsurface.batchlightmapcolor4f = NULL;
8161         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8162         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8163         rsurface.batchtexcoordtexture2f = NULL;
8164         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8165         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8166         rsurface.batchtexcoordlightmap2f = NULL;
8167         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8168         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8169         rsurface.batchvertexmesh = NULL;
8170         rsurface.batchvertexmeshbuffer = NULL;
8171         rsurface.batchvertex3fbuffer = NULL;
8172         rsurface.batchelement3i = NULL;
8173         rsurface.batchelement3i_indexbuffer = NULL;
8174         rsurface.batchelement3i_bufferoffset = 0;
8175         rsurface.batchelement3s = NULL;
8176         rsurface.batchelement3s_indexbuffer = NULL;
8177         rsurface.batchelement3s_bufferoffset = 0;
8178         rsurface.passcolor4f = NULL;
8179         rsurface.passcolor4f_vertexbuffer = NULL;
8180         rsurface.passcolor4f_bufferoffset = 0;
8181 }
8182
8183 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8184 {
8185         dp_model_t *model = ent->model;
8186         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8187         //      return;
8188         rsurface.entity = (entity_render_t *)ent;
8189         rsurface.skeleton = ent->skeleton;
8190         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8191         rsurface.ent_skinnum = ent->skinnum;
8192         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;
8193         rsurface.ent_flags = ent->flags;
8194         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8195         rsurface.matrix = ent->matrix;
8196         rsurface.inversematrix = ent->inversematrix;
8197         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8198         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8199         R_EntityMatrix(&rsurface.matrix);
8200         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8201         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8202         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8203         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8204         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8205         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8206         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8207         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8208         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8209         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8210         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8211         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8212         rsurface.colormod[3] = ent->alpha;
8213         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8214         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8215         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8216         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8217         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8218         if (ent->model->brush.submodel && !prepass)
8219         {
8220                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8221                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8222         }
8223         if (model->surfmesh.isanimated && model->AnimateVertices)
8224         {
8225                 if (ent->animcache_vertex3f)
8226                 {
8227                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8228                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8229                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8230                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8231                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8232                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8233                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8234                 }
8235                 else if (wanttangents)
8236                 {
8237                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8238                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8239                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8240                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8241                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8242                         rsurface.modelvertexmesh = NULL;
8243                         rsurface.modelvertexmeshbuffer = NULL;
8244                         rsurface.modelvertex3fbuffer = NULL;
8245                 }
8246                 else if (wantnormals)
8247                 {
8248                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8249                         rsurface.modelsvector3f = NULL;
8250                         rsurface.modeltvector3f = NULL;
8251                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8252                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8253                         rsurface.modelvertexmesh = NULL;
8254                         rsurface.modelvertexmeshbuffer = NULL;
8255                         rsurface.modelvertex3fbuffer = NULL;
8256                 }
8257                 else
8258                 {
8259                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8260                         rsurface.modelsvector3f = NULL;
8261                         rsurface.modeltvector3f = NULL;
8262                         rsurface.modelnormal3f = NULL;
8263                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8264                         rsurface.modelvertexmesh = NULL;
8265                         rsurface.modelvertexmeshbuffer = NULL;
8266                         rsurface.modelvertex3fbuffer = NULL;
8267                 }
8268                 rsurface.modelvertex3f_vertexbuffer = 0;
8269                 rsurface.modelvertex3f_bufferoffset = 0;
8270                 rsurface.modelsvector3f_vertexbuffer = 0;
8271                 rsurface.modelsvector3f_bufferoffset = 0;
8272                 rsurface.modeltvector3f_vertexbuffer = 0;
8273                 rsurface.modeltvector3f_bufferoffset = 0;
8274                 rsurface.modelnormal3f_vertexbuffer = 0;
8275                 rsurface.modelnormal3f_bufferoffset = 0;
8276                 rsurface.modelgeneratedvertex = true;
8277         }
8278         else
8279         {
8280                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8281                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8282                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8283                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8284                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8285                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8286                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8287                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8288                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8289                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8290                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8291                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8292                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8293                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8294                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8295                 rsurface.modelgeneratedvertex = false;
8296         }
8297         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8298         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8299         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8300         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8301         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8303         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8304         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8306         rsurface.modelelement3i = model->surfmesh.data_element3i;
8307         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8308         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8309         rsurface.modelelement3s = model->surfmesh.data_element3s;
8310         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8311         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8312         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8313         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8314         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8315         rsurface.modelsurfaces = model->data_surfaces;
8316         rsurface.batchgeneratedvertex = false;
8317         rsurface.batchfirstvertex = 0;
8318         rsurface.batchnumvertices = 0;
8319         rsurface.batchfirsttriangle = 0;
8320         rsurface.batchnumtriangles = 0;
8321         rsurface.batchvertex3f  = NULL;
8322         rsurface.batchvertex3f_vertexbuffer = NULL;
8323         rsurface.batchvertex3f_bufferoffset = 0;
8324         rsurface.batchsvector3f = NULL;
8325         rsurface.batchsvector3f_vertexbuffer = NULL;
8326         rsurface.batchsvector3f_bufferoffset = 0;
8327         rsurface.batchtvector3f = NULL;
8328         rsurface.batchtvector3f_vertexbuffer = NULL;
8329         rsurface.batchtvector3f_bufferoffset = 0;
8330         rsurface.batchnormal3f  = NULL;
8331         rsurface.batchnormal3f_vertexbuffer = NULL;
8332         rsurface.batchnormal3f_bufferoffset = 0;
8333         rsurface.batchlightmapcolor4f = NULL;
8334         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8335         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8336         rsurface.batchtexcoordtexture2f = NULL;
8337         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8338         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8339         rsurface.batchtexcoordlightmap2f = NULL;
8340         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8341         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8342         rsurface.batchvertexmesh = NULL;
8343         rsurface.batchvertexmeshbuffer = NULL;
8344         rsurface.batchvertex3fbuffer = NULL;
8345         rsurface.batchelement3i = NULL;
8346         rsurface.batchelement3i_indexbuffer = NULL;
8347         rsurface.batchelement3i_bufferoffset = 0;
8348         rsurface.batchelement3s = NULL;
8349         rsurface.batchelement3s_indexbuffer = NULL;
8350         rsurface.batchelement3s_bufferoffset = 0;
8351         rsurface.passcolor4f = NULL;
8352         rsurface.passcolor4f_vertexbuffer = NULL;
8353         rsurface.passcolor4f_bufferoffset = 0;
8354 }
8355
8356 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)
8357 {
8358         rsurface.entity = r_refdef.scene.worldentity;
8359         rsurface.skeleton = NULL;
8360         rsurface.ent_skinnum = 0;
8361         rsurface.ent_qwskin = -1;
8362         rsurface.ent_flags = entflags;
8363         rsurface.shadertime = r_refdef.scene.time - shadertime;
8364         rsurface.modelnumvertices = numvertices;
8365         rsurface.modelnumtriangles = numtriangles;
8366         rsurface.matrix = *matrix;
8367         rsurface.inversematrix = *inversematrix;
8368         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8369         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8370         R_EntityMatrix(&rsurface.matrix);
8371         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8372         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8373         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8374         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8375         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8376         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8377         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8378         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8379         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8380         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8381         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8382         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8383         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);
8384         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8385         rsurface.frameblend[0].lerp = 1;
8386         rsurface.ent_alttextures = false;
8387         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8388         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8389         if (wanttangents)
8390         {
8391                 rsurface.modelvertex3f = (float *)vertex3f;
8392                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8393                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8394                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8395         }
8396         else if (wantnormals)
8397         {
8398                 rsurface.modelvertex3f = (float *)vertex3f;
8399                 rsurface.modelsvector3f = NULL;
8400                 rsurface.modeltvector3f = NULL;
8401                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8402         }
8403         else
8404         {
8405                 rsurface.modelvertex3f = (float *)vertex3f;
8406                 rsurface.modelsvector3f = NULL;
8407                 rsurface.modeltvector3f = NULL;
8408                 rsurface.modelnormal3f = NULL;
8409         }
8410         rsurface.modelvertexmesh = NULL;
8411         rsurface.modelvertexmeshbuffer = NULL;
8412         rsurface.modelvertex3fbuffer = NULL;
8413         rsurface.modelvertex3f_vertexbuffer = 0;
8414         rsurface.modelvertex3f_bufferoffset = 0;
8415         rsurface.modelsvector3f_vertexbuffer = 0;
8416         rsurface.modelsvector3f_bufferoffset = 0;
8417         rsurface.modeltvector3f_vertexbuffer = 0;
8418         rsurface.modeltvector3f_bufferoffset = 0;
8419         rsurface.modelnormal3f_vertexbuffer = 0;
8420         rsurface.modelnormal3f_bufferoffset = 0;
8421         rsurface.modelgeneratedvertex = true;
8422         rsurface.modellightmapcolor4f  = (float *)color4f;
8423         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8424         rsurface.modellightmapcolor4f_bufferoffset = 0;
8425         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8426         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8427         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8428         rsurface.modeltexcoordlightmap2f  = NULL;
8429         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8430         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8431         rsurface.modelelement3i = (int *)element3i;
8432         rsurface.modelelement3i_indexbuffer = NULL;
8433         rsurface.modelelement3i_bufferoffset = 0;
8434         rsurface.modelelement3s = (unsigned short *)element3s;
8435         rsurface.modelelement3s_indexbuffer = NULL;
8436         rsurface.modelelement3s_bufferoffset = 0;
8437         rsurface.modellightmapoffsets = NULL;
8438         rsurface.modelsurfaces = NULL;
8439         rsurface.batchgeneratedvertex = false;
8440         rsurface.batchfirstvertex = 0;
8441         rsurface.batchnumvertices = 0;
8442         rsurface.batchfirsttriangle = 0;
8443         rsurface.batchnumtriangles = 0;
8444         rsurface.batchvertex3f  = NULL;
8445         rsurface.batchvertex3f_vertexbuffer = NULL;
8446         rsurface.batchvertex3f_bufferoffset = 0;
8447         rsurface.batchsvector3f = NULL;
8448         rsurface.batchsvector3f_vertexbuffer = NULL;
8449         rsurface.batchsvector3f_bufferoffset = 0;
8450         rsurface.batchtvector3f = NULL;
8451         rsurface.batchtvector3f_vertexbuffer = NULL;
8452         rsurface.batchtvector3f_bufferoffset = 0;
8453         rsurface.batchnormal3f  = NULL;
8454         rsurface.batchnormal3f_vertexbuffer = NULL;
8455         rsurface.batchnormal3f_bufferoffset = 0;
8456         rsurface.batchlightmapcolor4f = NULL;
8457         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8458         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8459         rsurface.batchtexcoordtexture2f = NULL;
8460         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8461         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8462         rsurface.batchtexcoordlightmap2f = NULL;
8463         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8464         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8465         rsurface.batchvertexmesh = NULL;
8466         rsurface.batchvertexmeshbuffer = NULL;
8467         rsurface.batchvertex3fbuffer = NULL;
8468         rsurface.batchelement3i = NULL;
8469         rsurface.batchelement3i_indexbuffer = NULL;
8470         rsurface.batchelement3i_bufferoffset = 0;
8471         rsurface.batchelement3s = NULL;
8472         rsurface.batchelement3s_indexbuffer = NULL;
8473         rsurface.batchelement3s_bufferoffset = 0;
8474         rsurface.passcolor4f = NULL;
8475         rsurface.passcolor4f_vertexbuffer = NULL;
8476         rsurface.passcolor4f_bufferoffset = 0;
8477
8478         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8479         {
8480                 if ((wantnormals || wanttangents) && !normal3f)
8481                 {
8482                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8483                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8484                 }
8485                 if (wanttangents && !svector3f)
8486                 {
8487                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8488                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8489                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8490                 }
8491         }
8492 }
8493
8494 float RSurf_FogPoint(const float *v)
8495 {
8496         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8497         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8498         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8499         float FogHeightFade = r_refdef.fogheightfade;
8500         float fogfrac;
8501         unsigned int fogmasktableindex;
8502         if (r_refdef.fogplaneviewabove)
8503                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8504         else
8505                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8506         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8507         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8508 }
8509
8510 float RSurf_FogVertex(const float *v)
8511 {
8512         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8513         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8514         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8515         float FogHeightFade = rsurface.fogheightfade;
8516         float fogfrac;
8517         unsigned int fogmasktableindex;
8518         if (r_refdef.fogplaneviewabove)
8519                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8520         else
8521                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8522         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8523         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8524 }
8525
8526 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8527 {
8528         int i;
8529         for (i = 0;i < numelements;i++)
8530                 outelement3i[i] = inelement3i[i] + adjust;
8531 }
8532
8533 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8534 extern cvar_t gl_vbo;
8535 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8536 {
8537         int deformindex;
8538         int firsttriangle;
8539         int numtriangles;
8540         int firstvertex;
8541         int endvertex;
8542         int numvertices;
8543         int surfacefirsttriangle;
8544         int surfacenumtriangles;
8545         int surfacefirstvertex;
8546         int surfaceendvertex;
8547         int surfacenumvertices;
8548         int batchnumvertices;
8549         int batchnumtriangles;
8550         int needsupdate;
8551         int i, j;
8552         qboolean gaps;
8553         qboolean dynamicvertex;
8554         float amplitude;
8555         float animpos;
8556         float scale;
8557         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8558         float waveparms[4];
8559         q3shaderinfo_deform_t *deform;
8560         const msurface_t *surface, *firstsurface;
8561         r_vertexmesh_t *vertexmesh;
8562         if (!texturenumsurfaces)
8563                 return;
8564         // find vertex range of this surface batch
8565         gaps = false;
8566         firstsurface = texturesurfacelist[0];
8567         firsttriangle = firstsurface->num_firsttriangle;
8568         batchnumvertices = 0;
8569         batchnumtriangles = 0;
8570         firstvertex = endvertex = firstsurface->num_firstvertex;
8571         for (i = 0;i < texturenumsurfaces;i++)
8572         {
8573                 surface = texturesurfacelist[i];
8574                 if (surface != firstsurface + i)
8575                         gaps = true;
8576                 surfacefirstvertex = surface->num_firstvertex;
8577                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8578                 surfacenumvertices = surface->num_vertices;
8579                 surfacenumtriangles = surface->num_triangles;
8580                 if (firstvertex > surfacefirstvertex)
8581                         firstvertex = surfacefirstvertex;
8582                 if (endvertex < surfaceendvertex)
8583                         endvertex = surfaceendvertex;
8584                 batchnumvertices += surfacenumvertices;
8585                 batchnumtriangles += surfacenumtriangles;
8586         }
8587
8588         // we now know the vertex range used, and if there are any gaps in it
8589         rsurface.batchfirstvertex = firstvertex;
8590         rsurface.batchnumvertices = endvertex - firstvertex;
8591         rsurface.batchfirsttriangle = firsttriangle;
8592         rsurface.batchnumtriangles = batchnumtriangles;
8593
8594         // this variable holds flags for which properties have been updated that
8595         // may require regenerating vertexmesh array...
8596         needsupdate = 0;
8597
8598         // check if any dynamic vertex processing must occur
8599         dynamicvertex = false;
8600
8601         // if there is a chance of animated vertex colors, it's a dynamic batch
8602         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8603         {
8604                 dynamicvertex = true;
8605                 batchneed |= BATCHNEED_NOGAPS;
8606                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8607         }
8608
8609         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8610         {
8611                 switch (deform->deform)
8612                 {
8613                 default:
8614                 case Q3DEFORM_PROJECTIONSHADOW:
8615                 case Q3DEFORM_TEXT0:
8616                 case Q3DEFORM_TEXT1:
8617                 case Q3DEFORM_TEXT2:
8618                 case Q3DEFORM_TEXT3:
8619                 case Q3DEFORM_TEXT4:
8620                 case Q3DEFORM_TEXT5:
8621                 case Q3DEFORM_TEXT6:
8622                 case Q3DEFORM_TEXT7:
8623                 case Q3DEFORM_NONE:
8624                         break;
8625                 case Q3DEFORM_AUTOSPRITE:
8626                         dynamicvertex = true;
8627                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8628                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8629                         break;
8630                 case Q3DEFORM_AUTOSPRITE2:
8631                         dynamicvertex = true;
8632                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8633                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8634                         break;
8635                 case Q3DEFORM_NORMAL:
8636                         dynamicvertex = true;
8637                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8638                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8639                         break;
8640                 case Q3DEFORM_WAVE:
8641                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8642                                 break; // if wavefunc is a nop, ignore this transform
8643                         dynamicvertex = true;
8644                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8645                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8646                         break;
8647                 case Q3DEFORM_BULGE:
8648                         dynamicvertex = true;
8649                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8650                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8651                         break;
8652                 case Q3DEFORM_MOVE:
8653                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8654                                 break; // if wavefunc is a nop, ignore this transform
8655                         dynamicvertex = true;
8656                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8657                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8658                         break;
8659                 }
8660         }
8661         switch(rsurface.texture->tcgen.tcgen)
8662         {
8663         default:
8664         case Q3TCGEN_TEXTURE:
8665                 break;
8666         case Q3TCGEN_LIGHTMAP:
8667                 dynamicvertex = true;
8668                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8669                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8670                 break;
8671         case Q3TCGEN_VECTOR:
8672                 dynamicvertex = true;
8673                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8674                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8675                 break;
8676         case Q3TCGEN_ENVIRONMENT:
8677                 dynamicvertex = true;
8678                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8679                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8680                 break;
8681         }
8682         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8683         {
8684                 dynamicvertex = true;
8685                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8686                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8687         }
8688
8689         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8690         {
8691                 dynamicvertex = true;
8692                 batchneed |= BATCHNEED_NOGAPS;
8693                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8694         }
8695
8696         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8697         {
8698                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8699                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8700                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8701                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8702                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8703                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8704                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8705         }
8706
8707         // when the model data has no vertex buffer (dynamic mesh), we need to
8708         // eliminate gaps
8709         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8710                 batchneed |= BATCHNEED_NOGAPS;
8711
8712         // if needsupdate, we have to do a dynamic vertex batch for sure
8713         if (needsupdate & batchneed)
8714                 dynamicvertex = true;
8715
8716         // see if we need to build vertexmesh from arrays
8717         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8718                 dynamicvertex = true;
8719
8720         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8721         // also some drivers strongly dislike firstvertex
8722         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8723                 dynamicvertex = true;
8724
8725         rsurface.batchvertex3f = rsurface.modelvertex3f;
8726         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8727         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8728         rsurface.batchsvector3f = rsurface.modelsvector3f;
8729         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8730         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8731         rsurface.batchtvector3f = rsurface.modeltvector3f;
8732         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8733         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8734         rsurface.batchnormal3f = rsurface.modelnormal3f;
8735         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8736         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8737         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8738         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8739         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8740         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8741         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8742         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8743         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8744         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8745         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8746         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8747         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8748         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8749         rsurface.batchelement3i = rsurface.modelelement3i;
8750         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8751         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8752         rsurface.batchelement3s = rsurface.modelelement3s;
8753         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8754         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8755
8756         // if any dynamic vertex processing has to occur in software, we copy the
8757         // entire surface list together before processing to rebase the vertices
8758         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8759         //
8760         // if any gaps exist and we do not have a static vertex buffer, we have to
8761         // copy the surface list together to avoid wasting upload bandwidth on the
8762         // vertices in the gaps.
8763         //
8764         // if gaps exist and we have a static vertex buffer, we still have to
8765         // combine the index buffer ranges into one dynamic index buffer.
8766         //
8767         // in all cases we end up with data that can be drawn in one call.
8768
8769         if (!dynamicvertex)
8770         {
8771                 // static vertex data, just set pointers...
8772                 rsurface.batchgeneratedvertex = false;
8773                 // if there are gaps, we want to build a combined index buffer,
8774                 // otherwise use the original static buffer with an appropriate offset
8775                 if (gaps)
8776                 {
8777                         // build a new triangle elements array for this batch
8778                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8779                         rsurface.batchfirsttriangle = 0;
8780                         numtriangles = 0;
8781                         for (i = 0;i < texturenumsurfaces;i++)
8782                         {
8783                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8784                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8785                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8786                                 numtriangles += surfacenumtriangles;
8787                         }
8788                         rsurface.batchelement3i_indexbuffer = NULL;
8789                         rsurface.batchelement3i_bufferoffset = 0;
8790                         rsurface.batchelement3s = NULL;
8791                         rsurface.batchelement3s_indexbuffer = NULL;
8792                         rsurface.batchelement3s_bufferoffset = 0;
8793                         if (endvertex <= 65536)
8794                         {
8795                                 // make a 16bit (unsigned short) index array if possible
8796                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8797                                 for (i = 0;i < numtriangles*3;i++)
8798                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8799                         }
8800                 }
8801                 return;
8802         }
8803
8804         // something needs software processing, do it for real...
8805         // we only directly handle separate array data in this case and then
8806         // generate interleaved data if needed...
8807         rsurface.batchgeneratedvertex = true;
8808
8809         // now copy the vertex data into a combined array and make an index array
8810         // (this is what Quake3 does all the time)
8811         //if (gaps || rsurface.batchfirstvertex)
8812         {
8813                 rsurface.batchvertex3fbuffer = NULL;
8814                 rsurface.batchvertexmesh = NULL;
8815                 rsurface.batchvertexmeshbuffer = NULL;
8816                 rsurface.batchvertex3f = NULL;
8817                 rsurface.batchvertex3f_vertexbuffer = NULL;
8818                 rsurface.batchvertex3f_bufferoffset = 0;
8819                 rsurface.batchsvector3f = NULL;
8820                 rsurface.batchsvector3f_vertexbuffer = NULL;
8821                 rsurface.batchsvector3f_bufferoffset = 0;
8822                 rsurface.batchtvector3f = NULL;
8823                 rsurface.batchtvector3f_vertexbuffer = NULL;
8824                 rsurface.batchtvector3f_bufferoffset = 0;
8825                 rsurface.batchnormal3f = NULL;
8826                 rsurface.batchnormal3f_vertexbuffer = NULL;
8827                 rsurface.batchnormal3f_bufferoffset = 0;
8828                 rsurface.batchlightmapcolor4f = NULL;
8829                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8830                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8831                 rsurface.batchtexcoordtexture2f = NULL;
8832                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8833                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8834                 rsurface.batchtexcoordlightmap2f = NULL;
8835                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8836                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8837                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8838                 rsurface.batchelement3i_indexbuffer = NULL;
8839                 rsurface.batchelement3i_bufferoffset = 0;
8840                 rsurface.batchelement3s = NULL;
8841                 rsurface.batchelement3s_indexbuffer = NULL;
8842                 rsurface.batchelement3s_bufferoffset = 0;
8843                 // we'll only be setting up certain arrays as needed
8844                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8845                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8846                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8847                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8848                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8849                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8850                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8851                 {
8852                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8853                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8854                 }
8855                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8856                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8857                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8858                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8859                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8860                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8861                 numvertices = 0;
8862                 numtriangles = 0;
8863                 for (i = 0;i < texturenumsurfaces;i++)
8864                 {
8865                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8866                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8867                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8868                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8869                         // copy only the data requested
8870                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8871                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8872                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8873                         {
8874                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8875                                 {
8876                                         if (rsurface.batchvertex3f)
8877                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8878                                         else
8879                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8880                                 }
8881                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8882                                 {
8883                                         if (rsurface.modelnormal3f)
8884                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8885                                         else
8886                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8887                                 }
8888                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8889                                 {
8890                                         if (rsurface.modelsvector3f)
8891                                         {
8892                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8893                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                         }
8895                                         else
8896                                         {
8897                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8899                                         }
8900                                 }
8901                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8902                                 {
8903                                         if (rsurface.modellightmapcolor4f)
8904                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8905                                         else
8906                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8907                                 }
8908                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8909                                 {
8910                                         if (rsurface.modeltexcoordtexture2f)
8911                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8912                                         else
8913                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8914                                 }
8915                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8916                                 {
8917                                         if (rsurface.modeltexcoordlightmap2f)
8918                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8919                                         else
8920                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8921                                 }
8922                         }
8923                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8924                         numvertices += surfacenumvertices;
8925                         numtriangles += surfacenumtriangles;
8926                 }
8927
8928                 // generate a 16bit index array as well if possible
8929                 // (in general, dynamic batches fit)
8930                 if (numvertices <= 65536)
8931                 {
8932                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8933                         for (i = 0;i < numtriangles*3;i++)
8934                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8935                 }
8936
8937                 // since we've copied everything, the batch now starts at 0
8938                 rsurface.batchfirstvertex = 0;
8939                 rsurface.batchnumvertices = batchnumvertices;
8940                 rsurface.batchfirsttriangle = 0;
8941                 rsurface.batchnumtriangles = batchnumtriangles;
8942         }
8943
8944         // q1bsp surfaces rendered in vertex color mode have to have colors
8945         // calculated based on lightstyles
8946         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8947         {
8948                 // generate color arrays for the surfaces in this list
8949                 int c[4];
8950                 int scale;
8951                 int size3;
8952                 const int *offsets;
8953                 const unsigned char *lm;
8954                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8955                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8956                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8957                 numvertices = 0;
8958                 for (i = 0;i < texturenumsurfaces;i++)
8959                 {
8960                         surface = texturesurfacelist[i];
8961                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8962                         surfacenumvertices = surface->num_vertices;
8963                         if (surface->lightmapinfo->samples)
8964                         {
8965                                 for (j = 0;j < surfacenumvertices;j++)
8966                                 {
8967                                         lm = surface->lightmapinfo->samples + offsets[j];
8968                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8969                                         VectorScale(lm, scale, c);
8970                                         if (surface->lightmapinfo->styles[1] != 255)
8971                                         {
8972                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8973                                                 lm += size3;
8974                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8975                                                 VectorMA(c, scale, lm, c);
8976                                                 if (surface->lightmapinfo->styles[2] != 255)
8977                                                 {
8978                                                         lm += size3;
8979                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8980                                                         VectorMA(c, scale, lm, c);
8981                                                         if (surface->lightmapinfo->styles[3] != 255)
8982                                                         {
8983                                                                 lm += size3;
8984                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8985                                                                 VectorMA(c, scale, lm, c);
8986                                                         }
8987                                                 }
8988                                         }
8989                                         c[0] >>= 7;
8990                                         c[1] >>= 7;
8991                                         c[2] >>= 7;
8992                                         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);
8993                                         numvertices++;
8994                                 }
8995                         }
8996                         else
8997                         {
8998                                 for (j = 0;j < surfacenumvertices;j++)
8999                                 {
9000                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9001                                         numvertices++;
9002                                 }
9003                         }
9004                 }
9005         }
9006
9007         // if vertices are deformed (sprite flares and things in maps, possibly
9008         // water waves, bulges and other deformations), modify the copied vertices
9009         // in place
9010         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9011         {
9012                 switch (deform->deform)
9013                 {
9014                 default:
9015                 case Q3DEFORM_PROJECTIONSHADOW:
9016                 case Q3DEFORM_TEXT0:
9017                 case Q3DEFORM_TEXT1:
9018                 case Q3DEFORM_TEXT2:
9019                 case Q3DEFORM_TEXT3:
9020                 case Q3DEFORM_TEXT4:
9021                 case Q3DEFORM_TEXT5:
9022                 case Q3DEFORM_TEXT6:
9023                 case Q3DEFORM_TEXT7:
9024                 case Q3DEFORM_NONE:
9025                         break;
9026                 case Q3DEFORM_AUTOSPRITE:
9027                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9029                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9030                         VectorNormalize(newforward);
9031                         VectorNormalize(newright);
9032                         VectorNormalize(newup);
9033 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9034 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9035 //                      rsurface.batchvertex3f_bufferoffset = 0;
9036 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9037 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9038 //                      rsurface.batchsvector3f_bufferoffset = 0;
9039 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9040 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9041 //                      rsurface.batchtvector3f_bufferoffset = 0;
9042 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9043 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9044 //                      rsurface.batchnormal3f_bufferoffset = 0;
9045                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9046                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9047                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9048                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9049                                 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);
9050                         // a single autosprite surface can contain multiple sprites...
9051                         for (j = 0;j < batchnumvertices - 3;j += 4)
9052                         {
9053                                 VectorClear(center);
9054                                 for (i = 0;i < 4;i++)
9055                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9056                                 VectorScale(center, 0.25f, center);
9057                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9058                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9059                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9060                                 for (i = 0;i < 4;i++)
9061                                 {
9062                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9063                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9064                                 }
9065                         }
9066                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9067                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9068                         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);
9069                         break;
9070                 case Q3DEFORM_AUTOSPRITE2:
9071                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9072                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9073                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9074                         VectorNormalize(newforward);
9075                         VectorNormalize(newright);
9076                         VectorNormalize(newup);
9077 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9078 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9079 //                      rsurface.batchvertex3f_bufferoffset = 0;
9080                         {
9081                                 const float *v1, *v2;
9082                                 vec3_t start, end;
9083                                 float f, l;
9084                                 struct
9085                                 {
9086                                         float length2;
9087                                         const float *v1;
9088                                         const float *v2;
9089                                 }
9090                                 shortest[2];
9091                                 memset(shortest, 0, sizeof(shortest));
9092                                 // a single autosprite surface can contain multiple sprites...
9093                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9094                                 {
9095                                         VectorClear(center);
9096                                         for (i = 0;i < 4;i++)
9097                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9098                                         VectorScale(center, 0.25f, center);
9099                                         // find the two shortest edges, then use them to define the
9100                                         // axis vectors for rotating around the central axis
9101                                         for (i = 0;i < 6;i++)
9102                                         {
9103                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9104                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9105                                                 l = VectorDistance2(v1, v2);
9106                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9107                                                 if (v1[2] != v2[2])
9108                                                         l += (1.0f / 1024.0f);
9109                                                 if (shortest[0].length2 > l || i == 0)
9110                                                 {
9111                                                         shortest[1] = shortest[0];
9112                                                         shortest[0].length2 = l;
9113                                                         shortest[0].v1 = v1;
9114                                                         shortest[0].v2 = v2;
9115                                                 }
9116                                                 else if (shortest[1].length2 > l || i == 1)
9117                                                 {
9118                                                         shortest[1].length2 = l;
9119                                                         shortest[1].v1 = v1;
9120                                                         shortest[1].v2 = v2;
9121                                                 }
9122                                         }
9123                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9124                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9125                                         // this calculates the right vector from the shortest edge
9126                                         // and the up vector from the edge midpoints
9127                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9128                                         VectorNormalize(right);
9129                                         VectorSubtract(end, start, up);
9130                                         VectorNormalize(up);
9131                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9132                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9133                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9134                                         VectorNegate(forward, forward);
9135                                         VectorReflect(forward, 0, up, forward);
9136                                         VectorNormalize(forward);
9137                                         CrossProduct(up, forward, newright);
9138                                         VectorNormalize(newright);
9139                                         // rotate the quad around the up axis vector, this is made
9140                                         // especially easy by the fact we know the quad is flat,
9141                                         // so we only have to subtract the center position and
9142                                         // measure distance along the right vector, and then
9143                                         // multiply that by the newright vector and add back the
9144                                         // center position
9145                                         // we also need to subtract the old position to undo the
9146                                         // displacement from the center, which we do with a
9147                                         // DotProduct, the subtraction/addition of center is also
9148                                         // optimized into DotProducts here
9149                                         l = DotProduct(right, center);
9150                                         for (i = 0;i < 4;i++)
9151                                         {
9152                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9153                                                 f = DotProduct(right, v1) - l;
9154                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9155                                         }
9156                                 }
9157                         }
9158                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9159                         {
9160 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9161 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9162 //                              rsurface.batchnormal3f_bufferoffset = 0;
9163                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9164                         }
9165                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9166                         {
9167 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9168 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9169 //                              rsurface.batchsvector3f_bufferoffset = 0;
9170 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9171 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9172 //                              rsurface.batchtvector3f_bufferoffset = 0;
9173                                 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);
9174                         }
9175                         break;
9176                 case Q3DEFORM_NORMAL:
9177                         // deform the normals to make reflections wavey
9178                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9179                         rsurface.batchnormal3f_vertexbuffer = NULL;
9180                         rsurface.batchnormal3f_bufferoffset = 0;
9181                         for (j = 0;j < batchnumvertices;j++)
9182                         {
9183                                 float vertex[3];
9184                                 float *normal = rsurface.batchnormal3f + 3*j;
9185                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9186                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9187                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9188                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9189                                 VectorNormalize(normal);
9190                         }
9191                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9192                         {
9193 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9194 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9195 //                              rsurface.batchsvector3f_bufferoffset = 0;
9196 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9197 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9198 //                              rsurface.batchtvector3f_bufferoffset = 0;
9199                                 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);
9200                         }
9201                         break;
9202                 case Q3DEFORM_WAVE:
9203                         // deform vertex array to make wavey water and flags and such
9204                         waveparms[0] = deform->waveparms[0];
9205                         waveparms[1] = deform->waveparms[1];
9206                         waveparms[2] = deform->waveparms[2];
9207                         waveparms[3] = deform->waveparms[3];
9208                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9209                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9210                         // this is how a divisor of vertex influence on deformation
9211                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9212                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9213 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9214 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9215 //                      rsurface.batchvertex3f_bufferoffset = 0;
9216 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9217 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9218 //                      rsurface.batchnormal3f_bufferoffset = 0;
9219                         for (j = 0;j < batchnumvertices;j++)
9220                         {
9221                                 // if the wavefunc depends on time, evaluate it per-vertex
9222                                 if (waveparms[3])
9223                                 {
9224                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9225                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9226                                 }
9227                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9228                         }
9229                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9230                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9231                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9232                         {
9233 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9234 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9235 //                              rsurface.batchsvector3f_bufferoffset = 0;
9236 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9237 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9238 //                              rsurface.batchtvector3f_bufferoffset = 0;
9239                                 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);
9240                         }
9241                         break;
9242                 case Q3DEFORM_BULGE:
9243                         // deform vertex array to make the surface have moving bulges
9244 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9245 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9246 //                      rsurface.batchvertex3f_bufferoffset = 0;
9247 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9248 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9249 //                      rsurface.batchnormal3f_bufferoffset = 0;
9250                         for (j = 0;j < batchnumvertices;j++)
9251                         {
9252                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9253                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9254                         }
9255                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9256                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9257                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9258                         {
9259 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9260 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9261 //                              rsurface.batchsvector3f_bufferoffset = 0;
9262 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9263 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9264 //                              rsurface.batchtvector3f_bufferoffset = 0;
9265                                 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);
9266                         }
9267                         break;
9268                 case Q3DEFORM_MOVE:
9269                         // deform vertex array
9270                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9271                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9272                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9273                         VectorScale(deform->parms, scale, waveparms);
9274 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9275 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9276 //                      rsurface.batchvertex3f_bufferoffset = 0;
9277                         for (j = 0;j < batchnumvertices;j++)
9278                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9279                         break;
9280                 }
9281         }
9282
9283         // generate texcoords based on the chosen texcoord source
9284         switch(rsurface.texture->tcgen.tcgen)
9285         {
9286         default:
9287         case Q3TCGEN_TEXTURE:
9288                 break;
9289         case Q3TCGEN_LIGHTMAP:
9290 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9291 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9292 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9293                 if (rsurface.batchtexcoordlightmap2f)
9294                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9295                 break;
9296         case Q3TCGEN_VECTOR:
9297 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9298 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9299 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9300                 for (j = 0;j < batchnumvertices;j++)
9301                 {
9302                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9303                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9304                 }
9305                 break;
9306         case Q3TCGEN_ENVIRONMENT:
9307                 // make environment reflections using a spheremap
9308                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 for (j = 0;j < batchnumvertices;j++)
9312                 {
9313                         // identical to Q3A's method, but executed in worldspace so
9314                         // carried models can be shiny too
9315
9316                         float viewer[3], d, reflected[3], worldreflected[3];
9317
9318                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9319                         // VectorNormalize(viewer);
9320
9321                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9322
9323                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9324                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9325                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9326                         // note: this is proportinal to viewer, so we can normalize later
9327
9328                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9329                         VectorNormalize(worldreflected);
9330
9331                         // note: this sphere map only uses world x and z!
9332                         // so positive and negative y will LOOK THE SAME.
9333                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9334                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9335                 }
9336                 break;
9337         }
9338         // the only tcmod that needs software vertex processing is turbulent, so
9339         // check for it here and apply the changes if needed
9340         // and we only support that as the first one
9341         // (handling a mixture of turbulent and other tcmods would be problematic
9342         //  without punting it entirely to a software path)
9343         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9344         {
9345                 amplitude = rsurface.texture->tcmods[0].parms[1];
9346                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9347 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9348 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9349 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9350                 for (j = 0;j < batchnumvertices;j++)
9351                 {
9352                         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);
9353                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9354                 }
9355         }
9356
9357         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9358         {
9359                 // convert the modified arrays to vertex structs
9360 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9361 //              rsurface.batchvertexmeshbuffer = NULL;
9362                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9363                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9364                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9365                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9366                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9367                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9368                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9369                 {
9370                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9371                         {
9372                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9373                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9374                         }
9375                 }
9376                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9377                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9378                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9379                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9380                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9381                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9382                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9383                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9384                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9385         }
9386 }
9387
9388 void RSurf_DrawBatch(void)
9389 {
9390         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9391         // through the pipeline, killing it earlier in the pipeline would have
9392         // per-surface overhead rather than per-batch overhead, so it's best to
9393         // reject it here, before it hits glDraw.
9394         if (rsurface.batchnumtriangles == 0)
9395                 return;
9396 #if 0
9397         // batch debugging code
9398         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9399         {
9400                 int i;
9401                 int j;
9402                 int c;
9403                 const int *e;
9404                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9405                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9406                 {
9407                         c = e[i];
9408                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9409                         {
9410                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9411                                 {
9412                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9413                                                 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);
9414                                         break;
9415                                 }
9416                         }
9417                 }
9418         }
9419 #endif
9420         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);
9421 }
9422
9423 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9424 {
9425         // pick the closest matching water plane
9426         int planeindex, vertexindex, bestplaneindex = -1;
9427         float d, bestd;
9428         vec3_t vert;
9429         const float *v;
9430         r_waterstate_waterplane_t *p;
9431         qboolean prepared = false;
9432         bestd = 0;
9433         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9434         {
9435                 if(p->camera_entity != rsurface.texture->camera_entity)
9436                         continue;
9437                 d = 0;
9438                 if(!prepared)
9439                 {
9440                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9441                         prepared = true;
9442                         if(rsurface.batchnumvertices == 0)
9443                                 break;
9444                 }
9445                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9446                 {
9447                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9448                         d += fabs(PlaneDiff(vert, &p->plane));
9449                 }
9450                 if (bestd > d || bestplaneindex < 0)
9451                 {
9452                         bestd = d;
9453                         bestplaneindex = planeindex;
9454                 }
9455         }
9456         return bestplaneindex;
9457         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9458         // this situation though, as it might be better to render single larger
9459         // batches with useless stuff (backface culled for example) than to
9460         // render multiple smaller batches
9461 }
9462
9463 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9464 {
9465         int i;
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;i < rsurface.batchnumvertices;i++)
9470                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9471 }
9472
9473 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9474 {
9475         int i;
9476         float f;
9477         const float *v;
9478         const float *c;
9479         float *c2;
9480         if (rsurface.passcolor4f)
9481         {
9482                 // generate color arrays
9483                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9484                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9485                 rsurface.passcolor4f_vertexbuffer = 0;
9486                 rsurface.passcolor4f_bufferoffset = 0;
9487                 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)
9488                 {
9489                         f = RSurf_FogVertex(v);
9490                         c2[0] = c[0] * f;
9491                         c2[1] = c[1] * f;
9492                         c2[2] = c[2] * f;
9493                         c2[3] = c[3];
9494                 }
9495         }
9496         else
9497         {
9498                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9499                 rsurface.passcolor4f_vertexbuffer = 0;
9500                 rsurface.passcolor4f_bufferoffset = 0;
9501                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9502                 {
9503                         f = RSurf_FogVertex(v);
9504                         c2[0] = f;
9505                         c2[1] = f;
9506                         c2[2] = f;
9507                         c2[3] = 1;
9508                 }
9509         }
9510 }
9511
9512 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9513 {
9514         int i;
9515         float f;
9516         const float *v;
9517         const float *c;
9518         float *c2;
9519         if (!rsurface.passcolor4f)
9520                 return;
9521         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9522         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9523         rsurface.passcolor4f_vertexbuffer = 0;
9524         rsurface.passcolor4f_bufferoffset = 0;
9525         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)
9526         {
9527                 f = RSurf_FogVertex(v);
9528                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9529                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9530                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9531                 c2[3] = c[3];
9532         }
9533 }
9534
9535 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9536 {
9537         int i;
9538         const float *c;
9539         float *c2;
9540         if (!rsurface.passcolor4f)
9541                 return;
9542         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9543         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9544         rsurface.passcolor4f_vertexbuffer = 0;
9545         rsurface.passcolor4f_bufferoffset = 0;
9546         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9547         {
9548                 c2[0] = c[0] * r;
9549                 c2[1] = c[1] * g;
9550                 c2[2] = c[2] * b;
9551                 c2[3] = c[3] * a;
9552         }
9553 }
9554
9555 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9556 {
9557         int i;
9558         const float *c;
9559         float *c2;
9560         if (!rsurface.passcolor4f)
9561                 return;
9562         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9563         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9564         rsurface.passcolor4f_vertexbuffer = 0;
9565         rsurface.passcolor4f_bufferoffset = 0;
9566         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9567         {
9568                 c2[0] = c[0] + r_refdef.scene.ambient;
9569                 c2[1] = c[1] + r_refdef.scene.ambient;
9570                 c2[2] = c[2] + r_refdef.scene.ambient;
9571                 c2[3] = c[3];
9572         }
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9576 {
9577         // TODO: optimize
9578         rsurface.passcolor4f = NULL;
9579         rsurface.passcolor4f_vertexbuffer = 0;
9580         rsurface.passcolor4f_bufferoffset = 0;
9581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9584         GL_Color(r, g, b, a);
9585         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9586         RSurf_DrawBatch();
9587 }
9588
9589 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9590 {
9591         // TODO: optimize applyfog && applycolor case
9592         // just apply fog if necessary, and tint the fog color array if necessary
9593         rsurface.passcolor4f = NULL;
9594         rsurface.passcolor4f_vertexbuffer = 0;
9595         rsurface.passcolor4f_bufferoffset = 0;
9596         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9597         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9598         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9599         GL_Color(r, g, b, a);
9600         RSurf_DrawBatch();
9601 }
9602
9603 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9604 {
9605         // TODO: optimize
9606         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9607         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9608         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9609         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9610         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9611         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9612         GL_Color(r, g, b, a);
9613         RSurf_DrawBatch();
9614 }
9615
9616 static void RSurf_DrawBatch_GL11_ClampColor(void)
9617 {
9618         int i;
9619         const float *c1;
9620         float *c2;
9621         if (!rsurface.passcolor4f)
9622                 return;
9623         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9624         {
9625                 c2[0] = bound(0.0f, c1[0], 1.0f);
9626                 c2[1] = bound(0.0f, c1[1], 1.0f);
9627                 c2[2] = bound(0.0f, c1[2], 1.0f);
9628                 c2[3] = bound(0.0f, c1[3], 1.0f);
9629         }
9630 }
9631
9632 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9633 {
9634         int i;
9635         float f;
9636         const float *v;
9637         const float *n;
9638         float *c;
9639         //vec3_t eyedir;
9640
9641         // fake shading
9642         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9643         rsurface.passcolor4f_vertexbuffer = 0;
9644         rsurface.passcolor4f_bufferoffset = 0;
9645         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)
9646         {
9647                 f = -DotProduct(r_refdef.view.forward, n);
9648                 f = max(0, f);
9649                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9650                 f *= r_refdef.lightmapintensity;
9651                 Vector4Set(c, f, f, f, 1);
9652         }
9653 }
9654
9655 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9656 {
9657         RSurf_DrawBatch_GL11_ApplyFakeLight();
9658         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9659         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9660         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9661         GL_Color(r, g, b, a);
9662         RSurf_DrawBatch();
9663 }
9664
9665 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9666 {
9667         int i;
9668         float f;
9669         float alpha;
9670         const float *v;
9671         const float *n;
9672         float *c;
9673         vec3_t ambientcolor;
9674         vec3_t diffusecolor;
9675         vec3_t lightdir;
9676         // TODO: optimize
9677         // model lighting
9678         VectorCopy(rsurface.modellight_lightdir, lightdir);
9679         f = 0.5f * r_refdef.lightmapintensity;
9680         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9681         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9682         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9683         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9684         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9685         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9686         alpha = *a;
9687         if (VectorLength2(diffusecolor) > 0)
9688         {
9689                 // q3-style directional shading
9690                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9691                 rsurface.passcolor4f_vertexbuffer = 0;
9692                 rsurface.passcolor4f_bufferoffset = 0;
9693                 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)
9694                 {
9695                         if ((f = DotProduct(n, lightdir)) > 0)
9696                                 VectorMA(ambientcolor, f, diffusecolor, c);
9697                         else
9698                                 VectorCopy(ambientcolor, c);
9699                         c[3] = alpha;
9700                 }
9701                 *r = 1;
9702                 *g = 1;
9703                 *b = 1;
9704                 *a = 1;
9705                 *applycolor = false;
9706         }
9707         else
9708         {
9709                 *r = ambientcolor[0];
9710                 *g = ambientcolor[1];
9711                 *b = ambientcolor[2];
9712                 rsurface.passcolor4f = NULL;
9713                 rsurface.passcolor4f_vertexbuffer = 0;
9714                 rsurface.passcolor4f_bufferoffset = 0;
9715         }
9716 }
9717
9718 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9719 {
9720         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9721         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9722         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9723         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9724         GL_Color(r, g, b, a);
9725         RSurf_DrawBatch();
9726 }
9727
9728 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9729 {
9730         int i;
9731         float f;
9732         const float *v;
9733         float *c;
9734
9735         // fake shading
9736         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9737         rsurface.passcolor4f_vertexbuffer = 0;
9738         rsurface.passcolor4f_bufferoffset = 0;
9739
9740         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9741         {
9742                 f = 1 - RSurf_FogVertex(v);
9743                 c[0] = r;
9744                 c[1] = g;
9745                 c[2] = b;
9746                 c[3] = f * a;
9747         }
9748 }
9749
9750 void RSurf_SetupDepthAndCulling(void)
9751 {
9752         // submodels are biased to avoid z-fighting with world surfaces that they
9753         // may be exactly overlapping (avoids z-fighting artifacts on certain
9754         // doors and things in Quake maps)
9755         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9756         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9757         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9758         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9759 }
9760
9761 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9762 {
9763         // transparent sky would be ridiculous
9764         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9765                 return;
9766         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9767         skyrenderlater = true;
9768         RSurf_SetupDepthAndCulling();
9769         GL_DepthMask(true);
9770         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9771         // skymasking on them, and Quake3 never did sky masking (unlike
9772         // software Quake and software Quake2), so disable the sky masking
9773         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9774         // and skymasking also looks very bad when noclipping outside the
9775         // level, so don't use it then either.
9776         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9777         {
9778                 R_Mesh_ResetTextureState();
9779                 if (skyrendermasked)
9780                 {
9781                         R_SetupShader_DepthOrShadow(false);
9782                         // depth-only (masking)
9783                         GL_ColorMask(0,0,0,0);
9784                         // just to make sure that braindead drivers don't draw
9785                         // anything despite that colormask...
9786                         GL_BlendFunc(GL_ZERO, GL_ONE);
9787                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9788                         if (rsurface.batchvertex3fbuffer)
9789                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9790                         else
9791                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9792                 }
9793                 else
9794                 {
9795                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9796                         // fog sky
9797                         GL_BlendFunc(GL_ONE, GL_ZERO);
9798                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9799                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9800                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9801                 }
9802                 RSurf_DrawBatch();
9803                 if (skyrendermasked)
9804                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9805         }
9806         R_Mesh_ResetTextureState();
9807         GL_Color(1, 1, 1, 1);
9808 }
9809
9810 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9811 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9812 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9813 {
9814         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9815                 return;
9816         if (prepass)
9817         {
9818                 // render screenspace normalmap to texture
9819                 GL_DepthMask(true);
9820                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9821                 RSurf_DrawBatch();
9822         }
9823
9824         // bind lightmap texture
9825
9826         // water/refraction/reflection/camera surfaces have to be handled specially
9827         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9828         {
9829                 int start, end, startplaneindex;
9830                 for (start = 0;start < texturenumsurfaces;start = end)
9831                 {
9832                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9833                         if(startplaneindex < 0)
9834                         {
9835                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9836                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9837                                 end = start + 1;
9838                                 continue;
9839                         }
9840                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9841                                 ;
9842                         // now that we have a batch using the same planeindex, render it
9843                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9844                         {
9845                                 // render water or distortion background
9846                                 GL_DepthMask(true);
9847                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9848                                 RSurf_DrawBatch();
9849                                 // blend surface on top
9850                                 GL_DepthMask(false);
9851                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9852                                 RSurf_DrawBatch();
9853                         }
9854                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9855                         {
9856                                 // render surface with reflection texture as input
9857                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9858                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9859                                 RSurf_DrawBatch();
9860                         }
9861                 }
9862                 return;
9863         }
9864
9865         // render surface batch normally
9866         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9867         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);
9868         RSurf_DrawBatch();
9869 }
9870
9871 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9872 {
9873         // OpenGL 1.3 path - anything not completely ancient
9874         qboolean applycolor;
9875         qboolean applyfog;
9876         int layerindex;
9877         const texturelayer_t *layer;
9878         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);
9879         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9880
9881         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9882         {
9883                 vec4_t layercolor;
9884                 int layertexrgbscale;
9885                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9886                 {
9887                         if (layerindex == 0)
9888                                 GL_AlphaTest(true);
9889                         else
9890                         {
9891                                 GL_AlphaTest(false);
9892                                 GL_DepthFunc(GL_EQUAL);
9893                         }
9894                 }
9895                 GL_DepthMask(layer->depthmask && writedepth);
9896                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9897                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9898                 {
9899                         layertexrgbscale = 4;
9900                         VectorScale(layer->color, 0.25f, layercolor);
9901                 }
9902                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9903                 {
9904                         layertexrgbscale = 2;
9905                         VectorScale(layer->color, 0.5f, layercolor);
9906                 }
9907                 else
9908                 {
9909                         layertexrgbscale = 1;
9910                         VectorScale(layer->color, 1.0f, layercolor);
9911                 }
9912                 layercolor[3] = layer->color[3];
9913                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9914                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9915                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9916                 switch (layer->type)
9917                 {
9918                 case TEXTURELAYERTYPE_LITTEXTURE:
9919                         // single-pass lightmapped texture with 2x rgbscale
9920                         R_Mesh_TexBind(0, r_texture_white);
9921                         R_Mesh_TexMatrix(0, NULL);
9922                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9923                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9924                         R_Mesh_TexBind(1, layer->texture);
9925                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9926                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9927                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9928                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9929                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9930                         else if (FAKELIGHT_ENABLED)
9931                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9932                         else if (rsurface.uselightmaptexture)
9933                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9934                         else
9935                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9936                         break;
9937                 case TEXTURELAYERTYPE_TEXTURE:
9938                         // singletexture unlit texture with transparency support
9939                         R_Mesh_TexBind(0, layer->texture);
9940                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9941                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9942                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9943                         R_Mesh_TexBind(1, 0);
9944                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9945                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9946                         break;
9947                 case TEXTURELAYERTYPE_FOG:
9948                         // singletexture fogging
9949                         if (layer->texture)
9950                         {
9951                                 R_Mesh_TexBind(0, layer->texture);
9952                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9953                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9954                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9955                         }
9956                         else
9957                         {
9958                                 R_Mesh_TexBind(0, 0);
9959                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9960                         }
9961                         R_Mesh_TexBind(1, 0);
9962                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9963                         // generate a color array for the fog pass
9964                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9965                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9966                         RSurf_DrawBatch();
9967                         break;
9968                 default:
9969                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9970                 }
9971         }
9972         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9973         {
9974                 GL_DepthFunc(GL_LEQUAL);
9975                 GL_AlphaTest(false);
9976         }
9977 }
9978
9979 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9980 {
9981         // OpenGL 1.1 - crusty old voodoo path
9982         qboolean applyfog;
9983         int layerindex;
9984         const texturelayer_t *layer;
9985         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);
9986         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9987
9988         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9989         {
9990                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9991                 {
9992                         if (layerindex == 0)
9993                                 GL_AlphaTest(true);
9994                         else
9995                         {
9996                                 GL_AlphaTest(false);
9997                                 GL_DepthFunc(GL_EQUAL);
9998                         }
9999                 }
10000                 GL_DepthMask(layer->depthmask && writedepth);
10001                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10002                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10003                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10004                 switch (layer->type)
10005                 {
10006                 case TEXTURELAYERTYPE_LITTEXTURE:
10007                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10008                         {
10009                                 // two-pass lit texture with 2x rgbscale
10010                                 // first the lightmap pass
10011                                 R_Mesh_TexBind(0, r_texture_white);
10012                                 R_Mesh_TexMatrix(0, NULL);
10013                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10014                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10015                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10016                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10017                                 else if (FAKELIGHT_ENABLED)
10018                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10019                                 else if (rsurface.uselightmaptexture)
10020                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10021                                 else
10022                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10023                                 // then apply the texture to it
10024                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10025                                 R_Mesh_TexBind(0, layer->texture);
10026                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10027                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10028                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10029                                 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);
10030                         }
10031                         else
10032                         {
10033                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10034                                 R_Mesh_TexBind(0, layer->texture);
10035                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10036                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10037                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10038                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10039                                         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);
10040                                 else
10041                                         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);
10042                         }
10043                         break;
10044                 case TEXTURELAYERTYPE_TEXTURE:
10045                         // singletexture unlit texture with transparency support
10046                         R_Mesh_TexBind(0, layer->texture);
10047                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10048                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10049                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10050                         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);
10051                         break;
10052                 case TEXTURELAYERTYPE_FOG:
10053                         // singletexture fogging
10054                         if (layer->texture)
10055                         {
10056                                 R_Mesh_TexBind(0, layer->texture);
10057                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10058                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10059                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10060                         }
10061                         else
10062                         {
10063                                 R_Mesh_TexBind(0, 0);
10064                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10065                         }
10066                         // generate a color array for the fog pass
10067                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10068                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10069                         RSurf_DrawBatch();
10070                         break;
10071                 default:
10072                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10073                 }
10074         }
10075         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10076         {
10077                 GL_DepthFunc(GL_LEQUAL);
10078                 GL_AlphaTest(false);
10079         }
10080 }
10081
10082 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10083 {
10084         int vi;
10085         int j;
10086         r_vertexgeneric_t *batchvertex;
10087         float c[4];
10088
10089 //      R_Mesh_ResetTextureState();
10090         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10091
10092         if(rsurface.texture && rsurface.texture->currentskinframe)
10093         {
10094                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10095                 c[3] *= rsurface.texture->currentalpha;
10096         }
10097         else
10098         {
10099                 c[0] = 1;
10100                 c[1] = 0;
10101                 c[2] = 1;
10102                 c[3] = 1;
10103         }
10104
10105         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10106         {
10107                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10108                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10109                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10110         }
10111
10112         // brighten it up (as texture value 127 means "unlit")
10113         c[0] *= 2 * r_refdef.view.colorscale;
10114         c[1] *= 2 * r_refdef.view.colorscale;
10115         c[2] *= 2 * r_refdef.view.colorscale;
10116
10117         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10118                 c[3] *= r_wateralpha.value;
10119
10120         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10121         {
10122                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10123                 GL_DepthMask(false);
10124         }
10125         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10126         {
10127                 GL_BlendFunc(GL_ONE, GL_ONE);
10128                 GL_DepthMask(false);
10129         }
10130         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10131         {
10132                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10133                 GL_DepthMask(false);
10134         }
10135         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10136         {
10137                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10138                 GL_DepthMask(false);
10139         }
10140         else
10141         {
10142                 GL_BlendFunc(GL_ONE, GL_ZERO);
10143                 GL_DepthMask(writedepth);
10144         }
10145
10146         if (r_showsurfaces.integer == 3)
10147         {
10148                 rsurface.passcolor4f = NULL;
10149
10150                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10151                 {
10152                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10153
10154                         rsurface.passcolor4f = NULL;
10155                         rsurface.passcolor4f_vertexbuffer = 0;
10156                         rsurface.passcolor4f_bufferoffset = 0;
10157                 }
10158                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10159                 {
10160                         qboolean applycolor = true;
10161                         float one = 1.0;
10162
10163                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10164
10165                         r_refdef.lightmapintensity = 1;
10166                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10167                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10168                 }
10169                 else if (FAKELIGHT_ENABLED)
10170                 {
10171                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172
10173                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10174                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10175                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10176                 }
10177                 else
10178                 {
10179                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10180
10181                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10182                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10183                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10184                 }
10185
10186                 if(!rsurface.passcolor4f)
10187                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10188
10189                 RSurf_DrawBatch_GL11_ApplyAmbient();
10190                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10191                 if(r_refdef.fogenabled)
10192                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10193                 RSurf_DrawBatch_GL11_ClampColor();
10194
10195                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10196                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10197                 RSurf_DrawBatch();
10198         }
10199         else if (!r_refdef.view.showdebug)
10200         {
10201                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10202                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10203                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10204                 {
10205                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10206                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10207                 }
10208                 R_Mesh_PrepareVertices_Generic_Unlock();
10209                 RSurf_DrawBatch();
10210         }
10211         else if (r_showsurfaces.integer == 4)
10212         {
10213                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10214                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10215                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10216                 {
10217                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10218                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10219                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10220                 }
10221                 R_Mesh_PrepareVertices_Generic_Unlock();
10222                 RSurf_DrawBatch();
10223         }
10224         else if (r_showsurfaces.integer == 2)
10225         {
10226                 const int *e;
10227                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10228                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10229                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10230                 {
10231                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10232                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10233                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10234                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10235                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10236                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10237                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10238                 }
10239                 R_Mesh_PrepareVertices_Generic_Unlock();
10240                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10241         }
10242         else
10243         {
10244                 int texturesurfaceindex;
10245                 int k;
10246                 const msurface_t *surface;
10247                 float surfacecolor4f[4];
10248                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10249                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10250                 vi = 0;
10251                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10252                 {
10253                         surface = texturesurfacelist[texturesurfaceindex];
10254                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10255                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10256                         for (j = 0;j < surface->num_vertices;j++)
10257                         {
10258                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10259                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10260                                 vi++;
10261                         }
10262                 }
10263                 R_Mesh_PrepareVertices_Generic_Unlock();
10264                 RSurf_DrawBatch();
10265         }
10266 }
10267
10268 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10269 {
10270         CHECKGLERROR
10271         RSurf_SetupDepthAndCulling();
10272         if (r_showsurfaces.integer)
10273         {
10274                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10275                 return;
10276         }
10277         switch (vid.renderpath)
10278         {
10279         case RENDERPATH_GL20:
10280         case RENDERPATH_D3D9:
10281         case RENDERPATH_D3D10:
10282         case RENDERPATH_D3D11:
10283         case RENDERPATH_SOFT:
10284         case RENDERPATH_GLES2:
10285                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10286                 break;
10287         case RENDERPATH_GL13:
10288         case RENDERPATH_GLES1:
10289                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10290                 break;
10291         case RENDERPATH_GL11:
10292                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10293                 break;
10294         }
10295         CHECKGLERROR
10296 }
10297
10298 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10299 {
10300         CHECKGLERROR
10301         RSurf_SetupDepthAndCulling();
10302         if (r_showsurfaces.integer)
10303         {
10304                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10305                 return;
10306         }
10307         switch (vid.renderpath)
10308         {
10309         case RENDERPATH_GL20:
10310         case RENDERPATH_D3D9:
10311         case RENDERPATH_D3D10:
10312         case RENDERPATH_D3D11:
10313         case RENDERPATH_SOFT:
10314         case RENDERPATH_GLES2:
10315                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10316                 break;
10317         case RENDERPATH_GL13:
10318         case RENDERPATH_GLES1:
10319                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10320                 break;
10321         case RENDERPATH_GL11:
10322                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10323                 break;
10324         }
10325         CHECKGLERROR
10326 }
10327
10328 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10329 {
10330         int i, j;
10331         int texturenumsurfaces, endsurface;
10332         texture_t *texture;
10333         const msurface_t *surface;
10334         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10335
10336         // if the model is static it doesn't matter what value we give for
10337         // wantnormals and wanttangents, so this logic uses only rules applicable
10338         // to a model, knowing that they are meaningless otherwise
10339         if (ent == r_refdef.scene.worldentity)
10340                 RSurf_ActiveWorldEntity();
10341         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10342                 RSurf_ActiveModelEntity(ent, false, false, false);
10343         else
10344         {
10345                 switch (vid.renderpath)
10346                 {
10347                 case RENDERPATH_GL20:
10348                 case RENDERPATH_D3D9:
10349                 case RENDERPATH_D3D10:
10350                 case RENDERPATH_D3D11:
10351                 case RENDERPATH_SOFT:
10352                 case RENDERPATH_GLES2:
10353                         RSurf_ActiveModelEntity(ent, true, true, false);
10354                         break;
10355                 case RENDERPATH_GL11:
10356                 case RENDERPATH_GL13:
10357                 case RENDERPATH_GLES1:
10358                         RSurf_ActiveModelEntity(ent, true, false, false);
10359                         break;
10360                 }
10361         }
10362
10363         if (r_transparentdepthmasking.integer)
10364         {
10365                 qboolean setup = false;
10366                 for (i = 0;i < numsurfaces;i = j)
10367                 {
10368                         j = i + 1;
10369                         surface = rsurface.modelsurfaces + surfacelist[i];
10370                         texture = surface->texture;
10371                         rsurface.texture = R_GetCurrentTexture(texture);
10372                         rsurface.lightmaptexture = NULL;
10373                         rsurface.deluxemaptexture = NULL;
10374                         rsurface.uselightmaptexture = false;
10375                         // scan ahead until we find a different texture
10376                         endsurface = min(i + 1024, numsurfaces);
10377                         texturenumsurfaces = 0;
10378                         texturesurfacelist[texturenumsurfaces++] = surface;
10379                         for (;j < endsurface;j++)
10380                         {
10381                                 surface = rsurface.modelsurfaces + surfacelist[j];
10382                                 if (texture != surface->texture)
10383                                         break;
10384                                 texturesurfacelist[texturenumsurfaces++] = surface;
10385                         }
10386                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10387                                 continue;
10388                         // render the range of surfaces as depth
10389                         if (!setup)
10390                         {
10391                                 setup = true;
10392                                 GL_ColorMask(0,0,0,0);
10393                                 GL_Color(1,1,1,1);
10394                                 GL_DepthTest(true);
10395                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10396                                 GL_DepthMask(true);
10397 //                              R_Mesh_ResetTextureState();
10398                                 R_SetupShader_DepthOrShadow(false);
10399                         }
10400                         RSurf_SetupDepthAndCulling();
10401                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10402                         if (rsurface.batchvertex3fbuffer)
10403                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10404                         else
10405                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10406                         RSurf_DrawBatch();
10407                 }
10408                 if (setup)
10409                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10410         }
10411
10412         for (i = 0;i < numsurfaces;i = j)
10413         {
10414                 j = i + 1;
10415                 surface = rsurface.modelsurfaces + surfacelist[i];
10416                 texture = surface->texture;
10417                 rsurface.texture = R_GetCurrentTexture(texture);
10418                 // scan ahead until we find a different texture
10419                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10420                 texturenumsurfaces = 0;
10421                 texturesurfacelist[texturenumsurfaces++] = surface;
10422                 if(FAKELIGHT_ENABLED)
10423                 {
10424                         rsurface.lightmaptexture = NULL;
10425                         rsurface.deluxemaptexture = NULL;
10426                         rsurface.uselightmaptexture = false;
10427                         for (;j < endsurface;j++)
10428                         {
10429                                 surface = rsurface.modelsurfaces + surfacelist[j];
10430                                 if (texture != surface->texture)
10431                                         break;
10432                                 texturesurfacelist[texturenumsurfaces++] = surface;
10433                         }
10434                 }
10435                 else
10436                 {
10437                         rsurface.lightmaptexture = surface->lightmaptexture;
10438                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10439                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10440                         for (;j < endsurface;j++)
10441                         {
10442                                 surface = rsurface.modelsurfaces + surfacelist[j];
10443                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10444                                         break;
10445                                 texturesurfacelist[texturenumsurfaces++] = surface;
10446                         }
10447                 }
10448                 // render the range of surfaces
10449                 if (ent == r_refdef.scene.worldentity)
10450                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10451                 else
10452                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10453         }
10454         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10455 }
10456
10457 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10458 {
10459         // transparent surfaces get pushed off into the transparent queue
10460         int surfacelistindex;
10461         const msurface_t *surface;
10462         vec3_t tempcenter, center;
10463         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10464         {
10465                 surface = texturesurfacelist[surfacelistindex];
10466                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10467                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10468                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10469                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10470                 if (queueentity->transparent_offset) // transparent offset
10471                 {
10472                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10473                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10474                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10475                 }
10476                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10477         }
10478 }
10479
10480 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10481 {
10482         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10483                 return;
10484         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10485                 return;
10486         RSurf_SetupDepthAndCulling();
10487         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10488         if (rsurface.batchvertex3fbuffer)
10489                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10490         else
10491                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10492         RSurf_DrawBatch();
10493 }
10494
10495 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10496 {
10497         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10498         CHECKGLERROR
10499         if (depthonly)
10500                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10501         else if (prepass)
10502         {
10503                 if (!rsurface.texture->currentnumlayers)
10504                         return;
10505                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10506                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10507                 else
10508                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10509         }
10510         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10511                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10512         else if (!rsurface.texture->currentnumlayers)
10513                 return;
10514         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10515         {
10516                 // in the deferred case, transparent surfaces were queued during prepass
10517                 if (!r_shadow_usingdeferredprepass)
10518                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10519         }
10520         else
10521         {
10522                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10523                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10524         }
10525         CHECKGLERROR
10526 }
10527
10528 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10529 {
10530         int i, j;
10531         texture_t *texture;
10532         R_FrameData_SetMark();
10533         // break the surface list down into batches by texture and use of lightmapping
10534         for (i = 0;i < numsurfaces;i = j)
10535         {
10536                 j = i + 1;
10537                 // texture is the base texture pointer, rsurface.texture is the
10538                 // current frame/skin the texture is directing us to use (for example
10539                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10540                 // use skin 1 instead)
10541                 texture = surfacelist[i]->texture;
10542                 rsurface.texture = R_GetCurrentTexture(texture);
10543                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10544                 {
10545                         // if this texture is not the kind we want, skip ahead to the next one
10546                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10547                                 ;
10548                         continue;
10549                 }
10550                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10551                 {
10552                         rsurface.lightmaptexture = NULL;
10553                         rsurface.deluxemaptexture = NULL;
10554                         rsurface.uselightmaptexture = false;
10555                         // simply scan ahead until we find a different texture or lightmap state
10556                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10557                                 ;
10558                 }
10559                 else
10560                 {
10561                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10562                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10563                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10564                         // simply scan ahead until we find a different texture or lightmap state
10565                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10566                                 ;
10567                 }
10568                 // render the range of surfaces
10569                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10570         }
10571         R_FrameData_ReturnToMark();
10572 }
10573
10574 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10575 {
10576         CHECKGLERROR
10577         if (depthonly)
10578                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10579         else if (prepass)
10580         {
10581                 if (!rsurface.texture->currentnumlayers)
10582                         return;
10583                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10584                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10585                 else
10586                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10587         }
10588         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10589                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10590         else if (!rsurface.texture->currentnumlayers)
10591                 return;
10592         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10593         {
10594                 // in the deferred case, transparent surfaces were queued during prepass
10595                 if (!r_shadow_usingdeferredprepass)
10596                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10597         }
10598         else
10599         {
10600                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10601                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10602         }
10603         CHECKGLERROR
10604 }
10605
10606 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10607 {
10608         int i, j;
10609         texture_t *texture;
10610         R_FrameData_SetMark();
10611         // break the surface list down into batches by texture and use of lightmapping
10612         for (i = 0;i < numsurfaces;i = j)
10613         {
10614                 j = i + 1;
10615                 // texture is the base texture pointer, rsurface.texture is the
10616                 // current frame/skin the texture is directing us to use (for example
10617                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10618                 // use skin 1 instead)
10619                 texture = surfacelist[i]->texture;
10620                 rsurface.texture = R_GetCurrentTexture(texture);
10621                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10622                 {
10623                         // if this texture is not the kind we want, skip ahead to the next one
10624                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10625                                 ;
10626                         continue;
10627                 }
10628                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10629                 {
10630                         rsurface.lightmaptexture = NULL;
10631                         rsurface.deluxemaptexture = NULL;
10632                         rsurface.uselightmaptexture = false;
10633                         // simply scan ahead until we find a different texture or lightmap state
10634                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10635                                 ;
10636                 }
10637                 else
10638                 {
10639                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10640                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10641                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10642                         // simply scan ahead until we find a different texture or lightmap state
10643                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10644                                 ;
10645                 }
10646                 // render the range of surfaces
10647                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10648         }
10649         R_FrameData_ReturnToMark();
10650 }
10651
10652 float locboxvertex3f[6*4*3] =
10653 {
10654         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10655         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10656         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10657         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10658         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10659         1,0,0, 0,0,0, 0,1,0, 1,1,0
10660 };
10661
10662 unsigned short locboxelements[6*2*3] =
10663 {
10664          0, 1, 2, 0, 2, 3,
10665          4, 5, 6, 4, 6, 7,
10666          8, 9,10, 8,10,11,
10667         12,13,14, 12,14,15,
10668         16,17,18, 16,18,19,
10669         20,21,22, 20,22,23
10670 };
10671
10672 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10673 {
10674         int i, j;
10675         cl_locnode_t *loc = (cl_locnode_t *)ent;
10676         vec3_t mins, size;
10677         float vertex3f[6*4*3];
10678         CHECKGLERROR
10679         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10680         GL_DepthMask(false);
10681         GL_DepthRange(0, 1);
10682         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10683         GL_DepthTest(true);
10684         GL_CullFace(GL_NONE);
10685         R_EntityMatrix(&identitymatrix);
10686
10687 //      R_Mesh_ResetTextureState();
10688
10689         i = surfacelist[0];
10690         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10691                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10692                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10693                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10694
10695         if (VectorCompare(loc->mins, loc->maxs))
10696         {
10697                 VectorSet(size, 2, 2, 2);
10698                 VectorMA(loc->mins, -0.5f, size, mins);
10699         }
10700         else
10701         {
10702                 VectorCopy(loc->mins, mins);
10703                 VectorSubtract(loc->maxs, loc->mins, size);
10704         }
10705
10706         for (i = 0;i < 6*4*3;)
10707                 for (j = 0;j < 3;j++, i++)
10708                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10709
10710         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10711         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10712         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10713 }
10714
10715 void R_DrawLocs(void)
10716 {
10717         int index;
10718         cl_locnode_t *loc, *nearestloc;
10719         vec3_t center;
10720         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10721         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10722         {
10723                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10724                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10725         }
10726 }
10727
10728 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10729 {
10730         if (decalsystem->decals)
10731                 Mem_Free(decalsystem->decals);
10732         memset(decalsystem, 0, sizeof(*decalsystem));
10733 }
10734
10735 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)
10736 {
10737         tridecal_t *decal;
10738         tridecal_t *decals;
10739         int i;
10740
10741         // expand or initialize the system
10742         if (decalsystem->maxdecals <= decalsystem->numdecals)
10743         {
10744                 decalsystem_t old = *decalsystem;
10745                 qboolean useshortelements;
10746                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10747                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10748                 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)));
10749                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10750                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10751                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10752                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10753                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10754                 if (decalsystem->numdecals)
10755                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10756                 if (old.decals)
10757                         Mem_Free(old.decals);
10758                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10759                         decalsystem->element3i[i] = i;
10760                 if (useshortelements)
10761                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10762                                 decalsystem->element3s[i] = i;
10763         }
10764
10765         // grab a decal and search for another free slot for the next one
10766         decals = decalsystem->decals;
10767         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10768         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10769                 ;
10770         decalsystem->freedecal = i;
10771         if (decalsystem->numdecals <= i)
10772                 decalsystem->numdecals = i + 1;
10773
10774         // initialize the decal
10775         decal->lived = 0;
10776         decal->triangleindex = triangleindex;
10777         decal->surfaceindex = surfaceindex;
10778         decal->decalsequence = decalsequence;
10779         decal->color4f[0][0] = c0[0];
10780         decal->color4f[0][1] = c0[1];
10781         decal->color4f[0][2] = c0[2];
10782         decal->color4f[0][3] = 1;
10783         decal->color4f[1][0] = c1[0];
10784         decal->color4f[1][1] = c1[1];
10785         decal->color4f[1][2] = c1[2];
10786         decal->color4f[1][3] = 1;
10787         decal->color4f[2][0] = c2[0];
10788         decal->color4f[2][1] = c2[1];
10789         decal->color4f[2][2] = c2[2];
10790         decal->color4f[2][3] = 1;
10791         decal->vertex3f[0][0] = v0[0];
10792         decal->vertex3f[0][1] = v0[1];
10793         decal->vertex3f[0][2] = v0[2];
10794         decal->vertex3f[1][0] = v1[0];
10795         decal->vertex3f[1][1] = v1[1];
10796         decal->vertex3f[1][2] = v1[2];
10797         decal->vertex3f[2][0] = v2[0];
10798         decal->vertex3f[2][1] = v2[1];
10799         decal->vertex3f[2][2] = v2[2];
10800         decal->texcoord2f[0][0] = t0[0];
10801         decal->texcoord2f[0][1] = t0[1];
10802         decal->texcoord2f[1][0] = t1[0];
10803         decal->texcoord2f[1][1] = t1[1];
10804         decal->texcoord2f[2][0] = t2[0];
10805         decal->texcoord2f[2][1] = t2[1];
10806         TriangleNormal(v0, v1, v2, decal->plane);
10807         VectorNormalize(decal->plane);
10808         decal->plane[3] = DotProduct(v0, decal->plane);
10809 }
10810
10811 extern cvar_t cl_decals_bias;
10812 extern cvar_t cl_decals_models;
10813 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10814 // baseparms, parms, temps
10815 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)
10816 {
10817         int cornerindex;
10818         int index;
10819         float v[9][3];
10820         const float *vertex3f;
10821         const float *normal3f;
10822         int numpoints;
10823         float points[2][9][3];
10824         float temp[3];
10825         float tc[9][2];
10826         float f;
10827         float c[9][4];
10828         const int *e;
10829
10830         e = rsurface.modelelement3i + 3*triangleindex;
10831
10832         vertex3f = rsurface.modelvertex3f;
10833         normal3f = rsurface.modelnormal3f;
10834
10835         if (normal3f)
10836         {
10837                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10838                 {
10839                         index = 3*e[cornerindex];
10840                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10841                 }
10842         }
10843         else
10844         {
10845                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10846                 {
10847                         index = 3*e[cornerindex];
10848                         VectorCopy(vertex3f + index, v[cornerindex]);
10849                 }
10850         }
10851
10852         // cull backfaces
10853         //TriangleNormal(v[0], v[1], v[2], normal);
10854         //if (DotProduct(normal, localnormal) < 0.0f)
10855         //      continue;
10856         // clip by each of the box planes formed from the projection matrix
10857         // if anything survives, we emit the decal
10858         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]);
10859         if (numpoints < 3)
10860                 return;
10861         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]);
10862         if (numpoints < 3)
10863                 return;
10864         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]);
10865         if (numpoints < 3)
10866                 return;
10867         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]);
10868         if (numpoints < 3)
10869                 return;
10870         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]);
10871         if (numpoints < 3)
10872                 return;
10873         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]);
10874         if (numpoints < 3)
10875                 return;
10876         // some part of the triangle survived, so we have to accept it...
10877         if (dynamic)
10878         {
10879                 // dynamic always uses the original triangle
10880                 numpoints = 3;
10881                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10882                 {
10883                         index = 3*e[cornerindex];
10884                         VectorCopy(vertex3f + index, v[cornerindex]);
10885                 }
10886         }
10887         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10888         {
10889                 // convert vertex positions to texcoords
10890                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10891                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10892                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10893                 // calculate distance fade from the projection origin
10894                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10895                 f = bound(0.0f, f, 1.0f);
10896                 c[cornerindex][0] = r * f;
10897                 c[cornerindex][1] = g * f;
10898                 c[cornerindex][2] = b * f;
10899                 c[cornerindex][3] = 1.0f;
10900                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10901         }
10902         if (dynamic)
10903                 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);
10904         else
10905                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10906                         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);
10907 }
10908 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)
10909 {
10910         matrix4x4_t projection;
10911         decalsystem_t *decalsystem;
10912         qboolean dynamic;
10913         dp_model_t *model;
10914         const msurface_t *surface;
10915         const msurface_t *surfaces;
10916         const int *surfacelist;
10917         const texture_t *texture;
10918         int numtriangles;
10919         int numsurfacelist;
10920         int surfacelistindex;
10921         int surfaceindex;
10922         int triangleindex;
10923         float localorigin[3];
10924         float localnormal[3];
10925         float localmins[3];
10926         float localmaxs[3];
10927         float localsize;
10928         //float normal[3];
10929         float planes[6][4];
10930         float angles[3];
10931         bih_t *bih;
10932         int bih_triangles_count;
10933         int bih_triangles[256];
10934         int bih_surfaces[256];
10935
10936         decalsystem = &ent->decalsystem;
10937         model = ent->model;
10938         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10939         {
10940                 R_DecalSystem_Reset(&ent->decalsystem);
10941                 return;
10942         }
10943
10944         if (!model->brush.data_leafs && !cl_decals_models.integer)
10945         {
10946                 if (decalsystem->model)
10947                         R_DecalSystem_Reset(decalsystem);
10948                 return;
10949         }
10950
10951         if (decalsystem->model != model)
10952                 R_DecalSystem_Reset(decalsystem);
10953         decalsystem->model = model;
10954
10955         RSurf_ActiveModelEntity(ent, true, false, false);
10956
10957         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10958         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10959         VectorNormalize(localnormal);
10960         localsize = worldsize*rsurface.inversematrixscale;
10961         localmins[0] = localorigin[0] - localsize;
10962         localmins[1] = localorigin[1] - localsize;
10963         localmins[2] = localorigin[2] - localsize;
10964         localmaxs[0] = localorigin[0] + localsize;
10965         localmaxs[1] = localorigin[1] + localsize;
10966         localmaxs[2] = localorigin[2] + localsize;
10967
10968         //VectorCopy(localnormal, planes[4]);
10969         //VectorVectors(planes[4], planes[2], planes[0]);
10970         AnglesFromVectors(angles, localnormal, NULL, false);
10971         AngleVectors(angles, planes[0], planes[2], planes[4]);
10972         VectorNegate(planes[0], planes[1]);
10973         VectorNegate(planes[2], planes[3]);
10974         VectorNegate(planes[4], planes[5]);
10975         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10976         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10977         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10978         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10979         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10980         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10981
10982 #if 1
10983 // works
10984 {
10985         matrix4x4_t forwardprojection;
10986         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10987         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10988 }
10989 #else
10990 // broken
10991 {
10992         float projectionvector[4][3];
10993         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10994         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10995         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10996         projectionvector[0][0] = planes[0][0] * ilocalsize;
10997         projectionvector[0][1] = planes[1][0] * ilocalsize;
10998         projectionvector[0][2] = planes[2][0] * ilocalsize;
10999         projectionvector[1][0] = planes[0][1] * ilocalsize;
11000         projectionvector[1][1] = planes[1][1] * ilocalsize;
11001         projectionvector[1][2] = planes[2][1] * ilocalsize;
11002         projectionvector[2][0] = planes[0][2] * ilocalsize;
11003         projectionvector[2][1] = planes[1][2] * ilocalsize;
11004         projectionvector[2][2] = planes[2][2] * ilocalsize;
11005         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11006         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11007         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11008         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11009 }
11010 #endif
11011
11012         dynamic = model->surfmesh.isanimated;
11013         numsurfacelist = model->nummodelsurfaces;
11014         surfacelist = model->sortedmodelsurfaces;
11015         surfaces = model->data_surfaces;
11016
11017         bih = NULL;
11018         bih_triangles_count = -1;
11019         if(!dynamic)
11020         {
11021                 if(model->render_bih.numleafs)
11022                         bih = &model->render_bih;
11023                 else if(model->collision_bih.numleafs)
11024                         bih = &model->collision_bih;
11025         }
11026         if(bih)
11027                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11028         if(bih_triangles_count == 0)
11029                 return;
11030         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11031                 return;
11032         if(bih_triangles_count > 0)
11033         {
11034                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11035                 {
11036                         surfaceindex = bih_surfaces[triangleindex];
11037                         surface = surfaces + surfaceindex;
11038                         texture = surface->texture;
11039                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11040                                 continue;
11041                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11042                                 continue;
11043                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11044                 }
11045         }
11046         else
11047         {
11048                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11049                 {
11050                         surfaceindex = surfacelist[surfacelistindex];
11051                         surface = surfaces + surfaceindex;
11052                         // check cull box first because it rejects more than any other check
11053                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11054                                 continue;
11055                         // skip transparent surfaces
11056                         texture = surface->texture;
11057                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11058                                 continue;
11059                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11060                                 continue;
11061                         numtriangles = surface->num_triangles;
11062                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11063                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11064                 }
11065         }
11066 }
11067
11068 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11069 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)
11070 {
11071         int renderentityindex;
11072         float worldmins[3];
11073         float worldmaxs[3];
11074         entity_render_t *ent;
11075
11076         if (!cl_decals_newsystem.integer)
11077                 return;
11078
11079         worldmins[0] = worldorigin[0] - worldsize;
11080         worldmins[1] = worldorigin[1] - worldsize;
11081         worldmins[2] = worldorigin[2] - worldsize;
11082         worldmaxs[0] = worldorigin[0] + worldsize;
11083         worldmaxs[1] = worldorigin[1] + worldsize;
11084         worldmaxs[2] = worldorigin[2] + worldsize;
11085
11086         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11087
11088         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11089         {
11090                 ent = r_refdef.scene.entities[renderentityindex];
11091                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11092                         continue;
11093
11094                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11095         }
11096 }
11097
11098 typedef struct r_decalsystem_splatqueue_s
11099 {
11100         vec3_t worldorigin;
11101         vec3_t worldnormal;
11102         float color[4];
11103         float tcrange[4];
11104         float worldsize;
11105         int decalsequence;
11106 }
11107 r_decalsystem_splatqueue_t;
11108
11109 int r_decalsystem_numqueued = 0;
11110 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11111
11112 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)
11113 {
11114         r_decalsystem_splatqueue_t *queue;
11115
11116         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11117                 return;
11118
11119         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11120         VectorCopy(worldorigin, queue->worldorigin);
11121         VectorCopy(worldnormal, queue->worldnormal);
11122         Vector4Set(queue->color, r, g, b, a);
11123         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11124         queue->worldsize = worldsize;
11125         queue->decalsequence = cl.decalsequence++;
11126 }
11127
11128 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11129 {
11130         int i;
11131         r_decalsystem_splatqueue_t *queue;
11132
11133         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11134                 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);
11135         r_decalsystem_numqueued = 0;
11136 }
11137
11138 extern cvar_t cl_decals_max;
11139 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11140 {
11141         int i;
11142         decalsystem_t *decalsystem = &ent->decalsystem;
11143         int numdecals;
11144         int killsequence;
11145         tridecal_t *decal;
11146         float frametime;
11147         float lifetime;
11148
11149         if (!decalsystem->numdecals)
11150                 return;
11151
11152         if (r_showsurfaces.integer)
11153                 return;
11154
11155         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11156         {
11157                 R_DecalSystem_Reset(decalsystem);
11158                 return;
11159         }
11160
11161         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11162         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11163
11164         if (decalsystem->lastupdatetime)
11165                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11166         else
11167                 frametime = 0;
11168         decalsystem->lastupdatetime = r_refdef.scene.time;
11169         decal = decalsystem->decals;
11170         numdecals = decalsystem->numdecals;
11171
11172         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11173         {
11174                 if (decal->color4f[0][3])
11175                 {
11176                         decal->lived += frametime;
11177                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11178                         {
11179                                 memset(decal, 0, sizeof(*decal));
11180                                 if (decalsystem->freedecal > i)
11181                                         decalsystem->freedecal = i;
11182                         }
11183                 }
11184         }
11185         decal = decalsystem->decals;
11186         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11187                 numdecals--;
11188
11189         // collapse the array by shuffling the tail decals into the gaps
11190         for (;;)
11191         {
11192                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11193                         decalsystem->freedecal++;
11194                 if (decalsystem->freedecal == numdecals)
11195                         break;
11196                 decal[decalsystem->freedecal] = decal[--numdecals];
11197         }
11198
11199         decalsystem->numdecals = numdecals;
11200
11201         if (numdecals <= 0)
11202         {
11203                 // if there are no decals left, reset decalsystem
11204                 R_DecalSystem_Reset(decalsystem);
11205         }
11206 }
11207
11208 extern skinframe_t *decalskinframe;
11209 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11210 {
11211         int i;
11212         decalsystem_t *decalsystem = &ent->decalsystem;
11213         int numdecals;
11214         tridecal_t *decal;
11215         float faderate;
11216         float alpha;
11217         float *v3f;
11218         float *c4f;
11219         float *t2f;
11220         const int *e;
11221         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11222         int numtris = 0;
11223
11224         numdecals = decalsystem->numdecals;
11225         if (!numdecals)
11226                 return;
11227
11228         if (r_showsurfaces.integer)
11229                 return;
11230
11231         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11232         {
11233                 R_DecalSystem_Reset(decalsystem);
11234                 return;
11235         }
11236
11237         // if the model is static it doesn't matter what value we give for
11238         // wantnormals and wanttangents, so this logic uses only rules applicable
11239         // to a model, knowing that they are meaningless otherwise
11240         if (ent == r_refdef.scene.worldentity)
11241                 RSurf_ActiveWorldEntity();
11242         else
11243                 RSurf_ActiveModelEntity(ent, false, false, false);
11244
11245         decalsystem->lastupdatetime = r_refdef.scene.time;
11246         decal = decalsystem->decals;
11247
11248         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11249
11250         // update vertex positions for animated models
11251         v3f = decalsystem->vertex3f;
11252         c4f = decalsystem->color4f;
11253         t2f = decalsystem->texcoord2f;
11254         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11255         {
11256                 if (!decal->color4f[0][3])
11257                         continue;
11258
11259                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11260                         continue;
11261
11262                 // skip backfaces
11263                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11264                         continue;
11265
11266                 // update color values for fading decals
11267                 if (decal->lived >= cl_decals_time.value)
11268                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11269                 else
11270                         alpha = 1.0f;
11271
11272                 c4f[ 0] = decal->color4f[0][0] * alpha;
11273                 c4f[ 1] = decal->color4f[0][1] * alpha;
11274                 c4f[ 2] = decal->color4f[0][2] * alpha;
11275                 c4f[ 3] = 1;
11276                 c4f[ 4] = decal->color4f[1][0] * alpha;
11277                 c4f[ 5] = decal->color4f[1][1] * alpha;
11278                 c4f[ 6] = decal->color4f[1][2] * alpha;
11279                 c4f[ 7] = 1;
11280                 c4f[ 8] = decal->color4f[2][0] * alpha;
11281                 c4f[ 9] = decal->color4f[2][1] * alpha;
11282                 c4f[10] = decal->color4f[2][2] * alpha;
11283                 c4f[11] = 1;
11284
11285                 t2f[0] = decal->texcoord2f[0][0];
11286                 t2f[1] = decal->texcoord2f[0][1];
11287                 t2f[2] = decal->texcoord2f[1][0];
11288                 t2f[3] = decal->texcoord2f[1][1];
11289                 t2f[4] = decal->texcoord2f[2][0];
11290                 t2f[5] = decal->texcoord2f[2][1];
11291
11292                 // update vertex positions for animated models
11293                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11294                 {
11295                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11296                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11297                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11298                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11299                 }
11300                 else
11301                 {
11302                         VectorCopy(decal->vertex3f[0], v3f);
11303                         VectorCopy(decal->vertex3f[1], v3f + 3);
11304                         VectorCopy(decal->vertex3f[2], v3f + 6);
11305                 }
11306
11307                 if (r_refdef.fogenabled)
11308                 {
11309                         alpha = RSurf_FogVertex(v3f);
11310                         VectorScale(c4f, alpha, c4f);
11311                         alpha = RSurf_FogVertex(v3f + 3);
11312                         VectorScale(c4f + 4, alpha, c4f + 4);
11313                         alpha = RSurf_FogVertex(v3f + 6);
11314                         VectorScale(c4f + 8, alpha, c4f + 8);
11315                 }
11316
11317                 v3f += 9;
11318                 c4f += 12;
11319                 t2f += 6;
11320                 numtris++;
11321         }
11322
11323         if (numtris > 0)
11324         {
11325                 r_refdef.stats.drawndecals += numtris;
11326
11327                 // now render the decals all at once
11328                 // (this assumes they all use one particle font texture!)
11329                 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);
11330 //              R_Mesh_ResetTextureState();
11331                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11332                 GL_DepthMask(false);
11333                 GL_DepthRange(0, 1);
11334                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11335                 GL_DepthTest(true);
11336                 GL_CullFace(GL_NONE);
11337                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11338                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11339                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11340         }
11341 }
11342
11343 static void R_DrawModelDecals(void)
11344 {
11345         int i, numdecals;
11346
11347         // fade faster when there are too many decals
11348         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11349         for (i = 0;i < r_refdef.scene.numentities;i++)
11350                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11351
11352         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11353         for (i = 0;i < r_refdef.scene.numentities;i++)
11354                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11355                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11356
11357         R_DecalSystem_ApplySplatEntitiesQueue();
11358
11359         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11360         for (i = 0;i < r_refdef.scene.numentities;i++)
11361                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11362
11363         r_refdef.stats.totaldecals += numdecals;
11364
11365         if (r_showsurfaces.integer)
11366                 return;
11367
11368         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11369
11370         for (i = 0;i < r_refdef.scene.numentities;i++)
11371         {
11372                 if (!r_refdef.viewcache.entityvisible[i])
11373                         continue;
11374                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11375                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11376         }
11377 }
11378
11379 extern cvar_t mod_collision_bih;
11380 void R_DrawDebugModel(void)
11381 {
11382         entity_render_t *ent = rsurface.entity;
11383         int i, j, k, l, flagsmask;
11384         const msurface_t *surface;
11385         dp_model_t *model = ent->model;
11386         vec3_t v;
11387
11388         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11389                 return;
11390
11391         if (r_showoverdraw.value > 0)
11392         {
11393                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11394                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11395                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11396                 GL_DepthTest(false);
11397                 GL_DepthMask(false);
11398                 GL_DepthRange(0, 1);
11399                 GL_BlendFunc(GL_ONE, GL_ONE);
11400                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11401                 {
11402                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11403                                 continue;
11404                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11405                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11406                         {
11407                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11408                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11409                                 if (!rsurface.texture->currentlayers->depthmask)
11410                                         GL_Color(c, 0, 0, 1.0f);
11411                                 else if (ent == r_refdef.scene.worldentity)
11412                                         GL_Color(c, c, c, 1.0f);
11413                                 else
11414                                         GL_Color(0, c, 0, 1.0f);
11415                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11416                                 RSurf_DrawBatch();
11417                         }
11418                 }
11419                 rsurface.texture = NULL;
11420         }
11421
11422         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11423
11424 //      R_Mesh_ResetTextureState();
11425         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11426         GL_DepthRange(0, 1);
11427         GL_DepthTest(!r_showdisabledepthtest.integer);
11428         GL_DepthMask(false);
11429         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11430
11431         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11432         {
11433                 int triangleindex;
11434                 int bihleafindex;
11435                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11436                 const q3mbrush_t *brush;
11437                 const bih_t *bih = &model->collision_bih;
11438                 const bih_leaf_t *bihleaf;
11439                 float vertex3f[3][3];
11440                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11441                 cullbox = false;
11442                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11443                 {
11444                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11445                                 continue;
11446                         switch (bihleaf->type)
11447                         {
11448                         case BIH_BRUSH:
11449                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11450                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11451                                 {
11452                                         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);
11453                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11454                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11455                                 }
11456                                 break;
11457                         case BIH_COLLISIONTRIANGLE:
11458                                 triangleindex = bihleaf->itemindex;
11459                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11460                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11461                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11462                                 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);
11463                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11464                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11465                                 break;
11466                         case BIH_RENDERTRIANGLE:
11467                                 triangleindex = bihleaf->itemindex;
11468                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11469                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11470                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11471                                 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);
11472                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11473                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11474                                 break;
11475                         }
11476                 }
11477         }
11478
11479         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11480
11481 #ifndef USE_GLES2
11482         if (r_showtris.integer && qglPolygonMode)
11483         {
11484                 if (r_showdisabledepthtest.integer)
11485                 {
11486                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11487                         GL_DepthMask(false);
11488                 }
11489                 else
11490                 {
11491                         GL_BlendFunc(GL_ONE, GL_ZERO);
11492                         GL_DepthMask(true);
11493                 }
11494                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11495                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11496                 {
11497                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11498                                 continue;
11499                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11500                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11501                         {
11502                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11503                                 if (!rsurface.texture->currentlayers->depthmask)
11504                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11505                                 else if (ent == r_refdef.scene.worldentity)
11506                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11507                                 else
11508                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11509                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11510                                 RSurf_DrawBatch();
11511                         }
11512                 }
11513                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11514                 rsurface.texture = NULL;
11515         }
11516
11517         if (r_shownormals.value != 0 && qglBegin)
11518         {
11519                 if (r_showdisabledepthtest.integer)
11520                 {
11521                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11522                         GL_DepthMask(false);
11523                 }
11524                 else
11525                 {
11526                         GL_BlendFunc(GL_ONE, GL_ZERO);
11527                         GL_DepthMask(true);
11528                 }
11529                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11530                 {
11531                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11532                                 continue;
11533                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11534                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11535                         {
11536                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11537                                 qglBegin(GL_LINES);
11538                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11539                                 {
11540                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11541                                         {
11542                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11543                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11544                                                 qglVertex3f(v[0], v[1], v[2]);
11545                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11546                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11547                                                 qglVertex3f(v[0], v[1], v[2]);
11548                                         }
11549                                 }
11550                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11551                                 {
11552                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11553                                         {
11554                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11555                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11556                                                 qglVertex3f(v[0], v[1], v[2]);
11557                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11558                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11559                                                 qglVertex3f(v[0], v[1], v[2]);
11560                                         }
11561                                 }
11562                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11563                                 {
11564                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11565                                         {
11566                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11567                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11570                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11571                                                 qglVertex3f(v[0], v[1], v[2]);
11572                                         }
11573                                 }
11574                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11575                                 {
11576                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11577                                         {
11578                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11579                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11580                                                 qglVertex3f(v[0], v[1], v[2]);
11581                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11582                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11583                                                 qglVertex3f(v[0], v[1], v[2]);
11584                                         }
11585                                 }
11586                                 qglEnd();
11587                                 CHECKGLERROR
11588                         }
11589                 }
11590                 rsurface.texture = NULL;
11591         }
11592 #endif
11593 }
11594
11595 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11596 int r_maxsurfacelist = 0;
11597 const msurface_t **r_surfacelist = NULL;
11598 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11599 {
11600         int i, j, endj, flagsmask;
11601         dp_model_t *model = r_refdef.scene.worldmodel;
11602         msurface_t *surfaces;
11603         unsigned char *update;
11604         int numsurfacelist = 0;
11605         if (model == NULL)
11606                 return;
11607
11608         if (r_maxsurfacelist < model->num_surfaces)
11609         {
11610                 r_maxsurfacelist = model->num_surfaces;
11611                 if (r_surfacelist)
11612                         Mem_Free((msurface_t**)r_surfacelist);
11613                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11614         }
11615
11616         RSurf_ActiveWorldEntity();
11617
11618         surfaces = model->data_surfaces;
11619         update = model->brushq1.lightmapupdateflags;
11620
11621         // update light styles on this submodel
11622         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11623         {
11624                 model_brush_lightstyleinfo_t *style;
11625                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11626                 {
11627                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11628                         {
11629                                 int *list = style->surfacelist;
11630                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11631                                 for (j = 0;j < style->numsurfaces;j++)
11632                                         update[list[j]] = true;
11633                         }
11634                 }
11635         }
11636
11637         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11638
11639         if (debug)
11640         {
11641                 R_DrawDebugModel();
11642                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11643                 return;
11644         }
11645
11646         rsurface.lightmaptexture = NULL;
11647         rsurface.deluxemaptexture = NULL;
11648         rsurface.uselightmaptexture = false;
11649         rsurface.texture = NULL;
11650         rsurface.rtlight = NULL;
11651         numsurfacelist = 0;
11652         // add visible surfaces to draw list
11653         for (i = 0;i < model->nummodelsurfaces;i++)
11654         {
11655                 j = model->sortedmodelsurfaces[i];
11656                 if (r_refdef.viewcache.world_surfacevisible[j])
11657                         r_surfacelist[numsurfacelist++] = surfaces + j;
11658         }
11659         // update lightmaps if needed
11660         if (model->brushq1.firstrender)
11661         {
11662                 model->brushq1.firstrender = false;
11663                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11664                         if (update[j])
11665                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11666         }
11667         else if (update)
11668         {
11669                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11670                         if (r_refdef.viewcache.world_surfacevisible[j])
11671                                 if (update[j])
11672                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11673         }
11674         // don't do anything if there were no surfaces
11675         if (!numsurfacelist)
11676         {
11677                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11678                 return;
11679         }
11680         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11681
11682         // add to stats if desired
11683         if (r_speeds.integer && !skysurfaces && !depthonly)
11684         {
11685                 r_refdef.stats.world_surfaces += numsurfacelist;
11686                 for (j = 0;j < numsurfacelist;j++)
11687                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11688         }
11689
11690         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11691 }
11692
11693 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11694 {
11695         int i, j, endj, flagsmask;
11696         dp_model_t *model = ent->model;
11697         msurface_t *surfaces;
11698         unsigned char *update;
11699         int numsurfacelist = 0;
11700         if (model == NULL)
11701                 return;
11702
11703         if (r_maxsurfacelist < model->num_surfaces)
11704         {
11705                 r_maxsurfacelist = model->num_surfaces;
11706                 if (r_surfacelist)
11707                         Mem_Free((msurface_t **)r_surfacelist);
11708                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11709         }
11710
11711         // if the model is static it doesn't matter what value we give for
11712         // wantnormals and wanttangents, so this logic uses only rules applicable
11713         // to a model, knowing that they are meaningless otherwise
11714         if (ent == r_refdef.scene.worldentity)
11715                 RSurf_ActiveWorldEntity();
11716         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11717                 RSurf_ActiveModelEntity(ent, false, false, false);
11718         else if (prepass)
11719                 RSurf_ActiveModelEntity(ent, true, true, true);
11720         else if (depthonly)
11721         {
11722                 switch (vid.renderpath)
11723                 {
11724                 case RENDERPATH_GL20:
11725                 case RENDERPATH_D3D9:
11726                 case RENDERPATH_D3D10:
11727                 case RENDERPATH_D3D11:
11728                 case RENDERPATH_SOFT:
11729                 case RENDERPATH_GLES2:
11730                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11731                         break;
11732                 case RENDERPATH_GL11:
11733                 case RENDERPATH_GL13:
11734                 case RENDERPATH_GLES1:
11735                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11736                         break;
11737                 }
11738         }
11739         else
11740         {
11741                 switch (vid.renderpath)
11742                 {
11743                 case RENDERPATH_GL20:
11744                 case RENDERPATH_D3D9:
11745                 case RENDERPATH_D3D10:
11746                 case RENDERPATH_D3D11:
11747                 case RENDERPATH_SOFT:
11748                 case RENDERPATH_GLES2:
11749                         RSurf_ActiveModelEntity(ent, true, true, false);
11750                         break;
11751                 case RENDERPATH_GL11:
11752                 case RENDERPATH_GL13:
11753                 case RENDERPATH_GLES1:
11754                         RSurf_ActiveModelEntity(ent, true, false, false);
11755                         break;
11756                 }
11757         }
11758
11759         surfaces = model->data_surfaces;
11760         update = model->brushq1.lightmapupdateflags;
11761
11762         // update light styles
11763         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11764         {
11765                 model_brush_lightstyleinfo_t *style;
11766                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11767                 {
11768                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11769                         {
11770                                 int *list = style->surfacelist;
11771                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11772                                 for (j = 0;j < style->numsurfaces;j++)
11773                                         update[list[j]] = true;
11774                         }
11775                 }
11776         }
11777
11778         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11779
11780         if (debug)
11781         {
11782                 R_DrawDebugModel();
11783                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11784                 return;
11785         }
11786
11787         rsurface.lightmaptexture = NULL;
11788         rsurface.deluxemaptexture = NULL;
11789         rsurface.uselightmaptexture = false;
11790         rsurface.texture = NULL;
11791         rsurface.rtlight = NULL;
11792         numsurfacelist = 0;
11793         // add visible surfaces to draw list
11794         for (i = 0;i < model->nummodelsurfaces;i++)
11795                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11796         // don't do anything if there were no surfaces
11797         if (!numsurfacelist)
11798         {
11799                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11800                 return;
11801         }
11802         // update lightmaps if needed
11803         if (update)
11804         {
11805                 int updated = 0;
11806                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11807                 {
11808                         if (update[j])
11809                         {
11810                                 updated++;
11811                                 R_BuildLightMap(ent, surfaces + j);
11812                         }
11813                 }
11814         }
11815         if (update)
11816                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11817                         if (update[j])
11818                                 R_BuildLightMap(ent, surfaces + j);
11819         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11820
11821         // add to stats if desired
11822         if (r_speeds.integer && !skysurfaces && !depthonly)
11823         {
11824                 r_refdef.stats.entities_surfaces += numsurfacelist;
11825                 for (j = 0;j < numsurfacelist;j++)
11826                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11827         }
11828
11829         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11830 }
11831
11832 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11833 {
11834         static texture_t texture;
11835         static msurface_t surface;
11836         const msurface_t *surfacelist = &surface;
11837
11838         // fake enough texture and surface state to render this geometry
11839
11840         texture.update_lastrenderframe = -1; // regenerate this texture
11841         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11842         texture.currentskinframe = skinframe;
11843         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11844         texture.offsetmapping = OFFSETMAPPING_OFF;
11845         texture.offsetscale = 1;
11846         texture.specularscalemod = 1;
11847         texture.specularpowermod = 1;
11848
11849         surface.texture = &texture;
11850         surface.num_triangles = numtriangles;
11851         surface.num_firsttriangle = firsttriangle;
11852         surface.num_vertices = numvertices;
11853         surface.num_firstvertex = firstvertex;
11854
11855         // now render it
11856         rsurface.texture = R_GetCurrentTexture(surface.texture);
11857         rsurface.lightmaptexture = NULL;
11858         rsurface.deluxemaptexture = NULL;
11859         rsurface.uselightmaptexture = false;
11860         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11861 }
11862
11863 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)
11864 {
11865         static msurface_t surface;
11866         const msurface_t *surfacelist = &surface;
11867
11868         // fake enough texture and surface state to render this geometry
11869         surface.texture = texture;
11870         surface.num_triangles = numtriangles;
11871         surface.num_firsttriangle = firsttriangle;
11872         surface.num_vertices = numvertices;
11873         surface.num_firstvertex = firstvertex;
11874
11875         // now render it
11876         rsurface.texture = R_GetCurrentTexture(surface.texture);
11877         rsurface.lightmaptexture = NULL;
11878         rsurface.deluxemaptexture = NULL;
11879         rsurface.uselightmaptexture = false;
11880         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11881 }