]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
9a9419f531f656164c097e007bc6c4a30e373fc8
[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 static struct r_bloomstate_s
234 {
235         qboolean enabled;
236         qboolean hdr;
237
238         int bloomwidth, bloomheight;
239
240         textype_t texturetype;
241         int viewfbo; // used to check if r_viewfbo cvar has changed
242
243         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
244         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
245         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
246
247         int screentexturewidth, screentextureheight;
248         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
249
250         int bloomtexturewidth, bloomtextureheight;
251         rtexture_t *texture_bloom;
252
253         // arrays for rendering the screen passes
254         float screentexcoord2f[8];
255         float bloomtexcoord2f[8];
256         float offsettexcoord2f[8];
257
258         r_viewport_t viewport;
259 }
260 r_bloomstate;
261
262 r_waterstate_t r_waterstate;
263
264 /// shadow volume bsp struct with automatically growing nodes buffer
265 svbsp_t r_svbsp;
266
267 rtexture_t *r_texture_blanknormalmap;
268 rtexture_t *r_texture_white;
269 rtexture_t *r_texture_grey128;
270 rtexture_t *r_texture_black;
271 rtexture_t *r_texture_notexture;
272 rtexture_t *r_texture_whitecube;
273 rtexture_t *r_texture_normalizationcube;
274 rtexture_t *r_texture_fogattenuation;
275 rtexture_t *r_texture_fogheighttexture;
276 rtexture_t *r_texture_gammaramps;
277 unsigned int r_texture_gammaramps_serial;
278 //rtexture_t *r_texture_fogintensity;
279 rtexture_t *r_texture_reflectcube;
280
281 // TODO: hash lookups?
282 typedef struct cubemapinfo_s
283 {
284         char basename[64];
285         rtexture_t *texture;
286 }
287 cubemapinfo_t;
288
289 int r_texture_numcubemaps;
290 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
291
292 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
293 unsigned int r_numqueries;
294 unsigned int r_maxqueries;
295
296 typedef struct r_qwskincache_s
297 {
298         char name[MAX_QPATH];
299         skinframe_t *skinframe;
300 }
301 r_qwskincache_t;
302
303 static r_qwskincache_t *r_qwskincache;
304 static int r_qwskincache_size;
305
306 /// vertex coordinates for a quad that covers the screen exactly
307 extern const float r_screenvertex3f[12];
308 extern const float r_d3dscreenvertex3f[12];
309 const float r_screenvertex3f[12] =
310 {
311         0, 0, 0,
312         1, 0, 0,
313         1, 1, 0,
314         0, 1, 0
315 };
316 const float r_d3dscreenvertex3f[12] =
317 {
318         0, 1, 0,
319         1, 1, 0,
320         1, 0, 0,
321         0, 0, 0
322 };
323
324 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
325 {
326         int i;
327         for (i = 0;i < verts;i++)
328         {
329                 out[0] = in[0] * r;
330                 out[1] = in[1] * g;
331                 out[2] = in[2] * b;
332                 out[3] = in[3];
333                 in += 4;
334                 out += 4;
335         }
336 }
337
338 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
339 {
340         int i;
341         for (i = 0;i < verts;i++)
342         {
343                 out[0] = r;
344                 out[1] = g;
345                 out[2] = b;
346                 out[3] = a;
347                 out += 4;
348         }
349 }
350
351 // FIXME: move this to client?
352 void FOG_clear(void)
353 {
354         if (gamemode == GAME_NEHAHRA)
355         {
356                 Cvar_Set("gl_fogenable", "0");
357                 Cvar_Set("gl_fogdensity", "0.2");
358                 Cvar_Set("gl_fogred", "0.3");
359                 Cvar_Set("gl_foggreen", "0.3");
360                 Cvar_Set("gl_fogblue", "0.3");
361         }
362         r_refdef.fog_density = 0;
363         r_refdef.fog_red = 0;
364         r_refdef.fog_green = 0;
365         r_refdef.fog_blue = 0;
366         r_refdef.fog_alpha = 1;
367         r_refdef.fog_start = 0;
368         r_refdef.fog_end = 16384;
369         r_refdef.fog_height = 1<<30;
370         r_refdef.fog_fadedepth = 128;
371         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
372 }
373
374 static void R_BuildBlankTextures(void)
375 {
376         unsigned char data[4];
377         data[2] = 128; // normal X
378         data[1] = 128; // normal Y
379         data[0] = 255; // normal Z
380         data[3] = 255; // height
381         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 255;
383         data[1] = 255;
384         data[2] = 255;
385         data[3] = 255;
386         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 128;
388         data[1] = 128;
389         data[2] = 128;
390         data[3] = 255;
391         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392         data[0] = 0;
393         data[1] = 0;
394         data[2] = 0;
395         data[3] = 255;
396         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
397 }
398
399 static void R_BuildNoTexture(void)
400 {
401         int x, y;
402         unsigned char pix[16][16][4];
403         // this makes a light grey/dark grey checkerboard texture
404         for (y = 0;y < 16;y++)
405         {
406                 for (x = 0;x < 16;x++)
407                 {
408                         if ((y < 8) ^ (x < 8))
409                         {
410                                 pix[y][x][0] = 128;
411                                 pix[y][x][1] = 128;
412                                 pix[y][x][2] = 128;
413                                 pix[y][x][3] = 255;
414                         }
415                         else
416                         {
417                                 pix[y][x][0] = 64;
418                                 pix[y][x][1] = 64;
419                                 pix[y][x][2] = 64;
420                                 pix[y][x][3] = 255;
421                         }
422                 }
423         }
424         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildWhiteCube(void)
428 {
429         unsigned char data[6*1*1*4];
430         memset(data, 255, sizeof(data));
431         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
432 }
433
434 static void R_BuildNormalizationCube(void)
435 {
436         int x, y, side;
437         vec3_t v;
438         vec_t s, t, intensity;
439 #define NORMSIZE 64
440         unsigned char *data;
441         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
442         for (side = 0;side < 6;side++)
443         {
444                 for (y = 0;y < NORMSIZE;y++)
445                 {
446                         for (x = 0;x < NORMSIZE;x++)
447                         {
448                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
449                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
450                                 switch(side)
451                                 {
452                                 default:
453                                 case 0:
454                                         v[0] = 1;
455                                         v[1] = -t;
456                                         v[2] = -s;
457                                         break;
458                                 case 1:
459                                         v[0] = -1;
460                                         v[1] = -t;
461                                         v[2] = s;
462                                         break;
463                                 case 2:
464                                         v[0] = s;
465                                         v[1] = 1;
466                                         v[2] = t;
467                                         break;
468                                 case 3:
469                                         v[0] = s;
470                                         v[1] = -1;
471                                         v[2] = -t;
472                                         break;
473                                 case 4:
474                                         v[0] = s;
475                                         v[1] = -t;
476                                         v[2] = 1;
477                                         break;
478                                 case 5:
479                                         v[0] = -s;
480                                         v[1] = -t;
481                                         v[2] = -1;
482                                         break;
483                                 }
484                                 intensity = 127.0f / sqrt(DotProduct(v, v));
485                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
486                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
487                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
488                                 data[((side*64+y)*64+x)*4+3] = 255;
489                         }
490                 }
491         }
492         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
493         Mem_Free(data);
494 }
495
496 static void R_BuildFogTexture(void)
497 {
498         int x, b;
499 #define FOGWIDTH 256
500         unsigned char data1[FOGWIDTH][4];
501         //unsigned char data2[FOGWIDTH][4];
502         double d, r, alpha;
503
504         r_refdef.fogmasktable_start = r_refdef.fog_start;
505         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
506         r_refdef.fogmasktable_range = r_refdef.fogrange;
507         r_refdef.fogmasktable_density = r_refdef.fog_density;
508
509         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
510         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
511         {
512                 d = (x * r - r_refdef.fogmasktable_start);
513                 if(developer_extra.integer)
514                         Con_DPrintf("%f ", d);
515                 d = max(0, d);
516                 if (r_fog_exp2.integer)
517                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
518                 else
519                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
520                 if(developer_extra.integer)
521                         Con_DPrintf(" : %f ", alpha);
522                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
523                 if(developer_extra.integer)
524                         Con_DPrintf(" = %f\n", alpha);
525                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
526         }
527
528         for (x = 0;x < FOGWIDTH;x++)
529         {
530                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
531                 data1[x][0] = b;
532                 data1[x][1] = b;
533                 data1[x][2] = b;
534                 data1[x][3] = 255;
535                 //data2[x][0] = 255 - b;
536                 //data2[x][1] = 255 - b;
537                 //data2[x][2] = 255 - b;
538                 //data2[x][3] = 255;
539         }
540         if (r_texture_fogattenuation)
541         {
542                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
543                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
544         }
545         else
546         {
547                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
548                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
549         }
550 }
551
552 static void R_BuildFogHeightTexture(void)
553 {
554         unsigned char *inpixels;
555         int size;
556         int x;
557         int y;
558         int j;
559         float c[4];
560         float f;
561         inpixels = NULL;
562         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
563         if (r_refdef.fogheighttexturename[0])
564                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
565         if (!inpixels)
566         {
567                 r_refdef.fog_height_tablesize = 0;
568                 if (r_texture_fogheighttexture)
569                         R_FreeTexture(r_texture_fogheighttexture);
570                 r_texture_fogheighttexture = NULL;
571                 if (r_refdef.fog_height_table2d)
572                         Mem_Free(r_refdef.fog_height_table2d);
573                 r_refdef.fog_height_table2d = NULL;
574                 if (r_refdef.fog_height_table1d)
575                         Mem_Free(r_refdef.fog_height_table1d);
576                 r_refdef.fog_height_table1d = NULL;
577                 return;
578         }
579         size = image_width;
580         r_refdef.fog_height_tablesize = size;
581         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
582         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
583         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
584         Mem_Free(inpixels);
585         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
586         // average fog color table accounting for every fog layer between a point
587         // and the camera.  (Note: attenuation is handled separately!)
588         for (y = 0;y < size;y++)
589         {
590                 for (x = 0;x < size;x++)
591                 {
592                         Vector4Clear(c);
593                         f = 0;
594                         if (x < y)
595                         {
596                                 for (j = x;j <= y;j++)
597                                 {
598                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
599                                         f++;
600                                 }
601                         }
602                         else
603                         {
604                                 for (j = x;j >= y;j--)
605                                 {
606                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
607                                         f++;
608                                 }
609                         }
610                         f = 1.0f / f;
611                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
612                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
613                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
614                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
615                 }
616         }
617         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
618 }
619
620 //=======================================================================================================================================================
621
622 static const char *builtinshaderstring =
623 #include "shader_glsl.h"
624 ;
625
626 const char *builtinhlslshaderstring =
627 #include "shader_hlsl.h"
628 ;
629
630 char *glslshaderstring = NULL;
631 char *hlslshaderstring = NULL;
632
633 //=======================================================================================================================================================
634
635 typedef struct shaderpermutationinfo_s
636 {
637         const char *pretext;
638         const char *name;
639 }
640 shaderpermutationinfo_t;
641
642 typedef struct shadermodeinfo_s
643 {
644         const char *vertexfilename;
645         const char *geometryfilename;
646         const char *fragmentfilename;
647         const char *pretext;
648         const char *name;
649 }
650 shadermodeinfo_t;
651
652 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
653 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
654 {
655         {"#define USEDIFFUSE\n", " diffuse"},
656         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
657         {"#define USEVIEWTINT\n", " viewtint"},
658         {"#define USECOLORMAPPING\n", " colormapping"},
659         {"#define USESATURATION\n", " saturation"},
660         {"#define USEFOGINSIDE\n", " foginside"},
661         {"#define USEFOGOUTSIDE\n", " fogoutside"},
662         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
663         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
664         {"#define USEGAMMARAMPS\n", " gammaramps"},
665         {"#define USECUBEFILTER\n", " cubefilter"},
666         {"#define USEGLOW\n", " glow"},
667         {"#define USEBLOOM\n", " bloom"},
668         {"#define USESPECULAR\n", " specular"},
669         {"#define USEPOSTPROCESSING\n", " postprocessing"},
670         {"#define USEREFLECTION\n", " reflection"},
671         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
672         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
673         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
674         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
675         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
676         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
677         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
678         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
679         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
680         {"#define USEALPHAKILL\n", " alphakill"},
681         {"#define USEREFLECTCUBE\n", " reflectcube"},
682         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
683         {"#define USEBOUNCEGRID\n", " bouncegrid"},
684         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
685         {"#define USETRIPPY\n", " trippy"},
686 };
687
688 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
689 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
690 {
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
704         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
705         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
706         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
707         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
708         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
709 };
710
711 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
712 {
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
726         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
727         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
728         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
729         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
730         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
731 };
732
733 struct r_glsl_permutation_s;
734 typedef struct r_glsl_permutation_s
735 {
736         /// hash lookup data
737         struct r_glsl_permutation_s *hashnext;
738         unsigned int mode;
739         unsigned int permutation;
740
741         /// indicates if we have tried compiling this permutation already
742         qboolean compiled;
743         /// 0 if compilation failed
744         int program;
745         // texture units assigned to each detected uniform
746         int tex_Texture_First;
747         int tex_Texture_Second;
748         int tex_Texture_GammaRamps;
749         int tex_Texture_Normal;
750         int tex_Texture_Color;
751         int tex_Texture_Gloss;
752         int tex_Texture_Glow;
753         int tex_Texture_SecondaryNormal;
754         int tex_Texture_SecondaryColor;
755         int tex_Texture_SecondaryGloss;
756         int tex_Texture_SecondaryGlow;
757         int tex_Texture_Pants;
758         int tex_Texture_Shirt;
759         int tex_Texture_FogHeightTexture;
760         int tex_Texture_FogMask;
761         int tex_Texture_Lightmap;
762         int tex_Texture_Deluxemap;
763         int tex_Texture_Attenuation;
764         int tex_Texture_Cube;
765         int tex_Texture_Refraction;
766         int tex_Texture_Reflection;
767         int tex_Texture_ShadowMap2D;
768         int tex_Texture_CubeProjection;
769         int tex_Texture_ScreenDepth;
770         int tex_Texture_ScreenNormalMap;
771         int tex_Texture_ScreenDiffuse;
772         int tex_Texture_ScreenSpecular;
773         int tex_Texture_ReflectMask;
774         int tex_Texture_ReflectCube;
775         int tex_Texture_BounceGrid;
776         /// locations of detected uniforms in program object, or -1 if not found
777         int loc_Texture_First;
778         int loc_Texture_Second;
779         int loc_Texture_GammaRamps;
780         int loc_Texture_Normal;
781         int loc_Texture_Color;
782         int loc_Texture_Gloss;
783         int loc_Texture_Glow;
784         int loc_Texture_SecondaryNormal;
785         int loc_Texture_SecondaryColor;
786         int loc_Texture_SecondaryGloss;
787         int loc_Texture_SecondaryGlow;
788         int loc_Texture_Pants;
789         int loc_Texture_Shirt;
790         int loc_Texture_FogHeightTexture;
791         int loc_Texture_FogMask;
792         int loc_Texture_Lightmap;
793         int loc_Texture_Deluxemap;
794         int loc_Texture_Attenuation;
795         int loc_Texture_Cube;
796         int loc_Texture_Refraction;
797         int loc_Texture_Reflection;
798         int loc_Texture_ShadowMap2D;
799         int loc_Texture_CubeProjection;
800         int loc_Texture_ScreenDepth;
801         int loc_Texture_ScreenNormalMap;
802         int loc_Texture_ScreenDiffuse;
803         int loc_Texture_ScreenSpecular;
804         int loc_Texture_ReflectMask;
805         int loc_Texture_ReflectCube;
806         int loc_Texture_BounceGrid;
807         int loc_Alpha;
808         int loc_BloomBlur_Parameters;
809         int loc_ClientTime;
810         int loc_Color_Ambient;
811         int loc_Color_Diffuse;
812         int loc_Color_Specular;
813         int loc_Color_Glow;
814         int loc_Color_Pants;
815         int loc_Color_Shirt;
816         int loc_DeferredColor_Ambient;
817         int loc_DeferredColor_Diffuse;
818         int loc_DeferredColor_Specular;
819         int loc_DeferredMod_Diffuse;
820         int loc_DeferredMod_Specular;
821         int loc_DistortScaleRefractReflect;
822         int loc_EyePosition;
823         int loc_FogColor;
824         int loc_FogHeightFade;
825         int loc_FogPlane;
826         int loc_FogPlaneViewDist;
827         int loc_FogRangeRecip;
828         int loc_LightColor;
829         int loc_LightDir;
830         int loc_LightPosition;
831         int loc_OffsetMapping_ScaleSteps;
832         int loc_OffsetMapping_LodDistance;
833         int loc_OffsetMapping_Bias;
834         int loc_PixelSize;
835         int loc_ReflectColor;
836         int loc_ReflectFactor;
837         int loc_ReflectOffset;
838         int loc_RefractColor;
839         int loc_Saturation;
840         int loc_ScreenCenterRefractReflect;
841         int loc_ScreenScaleRefractReflect;
842         int loc_ScreenToDepth;
843         int loc_ShadowMap_Parameters;
844         int loc_ShadowMap_TextureScale;
845         int loc_SpecularPower;
846         int loc_UserVec1;
847         int loc_UserVec2;
848         int loc_UserVec3;
849         int loc_UserVec4;
850         int loc_ViewTintColor;
851         int loc_ViewToLight;
852         int loc_ModelToLight;
853         int loc_TexMatrix;
854         int loc_BackgroundTexMatrix;
855         int loc_ModelViewProjectionMatrix;
856         int loc_ModelViewMatrix;
857         int loc_PixelToScreenTexCoord;
858         int loc_ModelToReflectCube;
859         int loc_ShadowMapMatrix;
860         int loc_BloomColorSubtract;
861         int loc_NormalmapScrollBlend;
862         int loc_BounceGridMatrix;
863         int loc_BounceGridIntensity;
864 }
865 r_glsl_permutation_t;
866
867 #define SHADERPERMUTATION_HASHSIZE 256
868
869
870 // non-degradable "lightweight" shader parameters to keep the permutations simpler
871 // these can NOT degrade! only use for simple stuff
872 enum
873 {
874         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
875         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
876         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
878         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
879         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
880         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
881         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
882 };
883 #define SHADERSTATICPARMS_COUNT 8
884
885 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
886 static int shaderstaticparms_count = 0;
887
888 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
889 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
890 qboolean R_CompileShader_CheckStaticParms(void)
891 {
892         static int r_compileshader_staticparms_save[1];
893         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
894         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
895
896         // detect all
897         if (r_glsl_saturation_redcompensate.integer)
898                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
899         if (r_glsl_vertextextureblend_usebothalphas.integer)
900                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
901         if (r_shadow_glossexact.integer)
902                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
903         if (r_glsl_postprocess.integer)
904         {
905                 if (r_glsl_postprocess_uservec1_enable.integer)
906                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
907                 if (r_glsl_postprocess_uservec2_enable.integer)
908                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
909                 if (r_glsl_postprocess_uservec3_enable.integer)
910                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
911                 if (r_glsl_postprocess_uservec4_enable.integer)
912                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
913         }
914         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
915                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
916         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
917 }
918
919 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
920         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
921                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
922         else \
923                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
924 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
925 {
926         shaderstaticparms_count = 0;
927
928         // emit all
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
937 }
938
939 /// information about each possible shader permutation
940 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
941 /// currently selected permutation
942 r_glsl_permutation_t *r_glsl_permutation;
943 /// storage for permutations linked in the hash table
944 memexpandablearray_t r_glsl_permutationarray;
945
946 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
947 {
948         //unsigned int hashdepth = 0;
949         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
950         r_glsl_permutation_t *p;
951         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
952         {
953                 if (p->mode == mode && p->permutation == permutation)
954                 {
955                         //if (hashdepth > 10)
956                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957                         return p;
958                 }
959                 //hashdepth++;
960         }
961         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
962         p->mode = mode;
963         p->permutation = permutation;
964         p->hashnext = r_glsl_permutationhash[mode][hashindex];
965         r_glsl_permutationhash[mode][hashindex] = p;
966         //if (hashdepth > 10)
967         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
968         return p;
969 }
970
971 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
972 {
973         char *shaderstring;
974         if (!filename || !filename[0])
975                 return NULL;
976         if (!strcmp(filename, "glsl/default.glsl"))
977         {
978                 if (!glslshaderstring)
979                 {
980                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
981                         if (glslshaderstring)
982                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
983                         else
984                                 glslshaderstring = (char *)builtinshaderstring;
985                 }
986                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
987                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
988                 return shaderstring;
989         }
990         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
991         if (shaderstring)
992         {
993                 if (printfromdisknotice)
994                         Con_DPrintf("from disk %s... ", filename);
995                 return shaderstring;
996         }
997         return shaderstring;
998 }
999
1000 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1001 {
1002         int i;
1003         int sampler;
1004         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1005         char *vertexstring, *geometrystring, *fragmentstring;
1006         char permutationname[256];
1007         int vertstrings_count = 0;
1008         int geomstrings_count = 0;
1009         int fragstrings_count = 0;
1010         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1011         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1012         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1013
1014         if (p->compiled)
1015                 return;
1016         p->compiled = true;
1017         p->program = 0;
1018
1019         permutationname[0] = 0;
1020         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1021         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1022         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1023
1024         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1025
1026         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1027         if(vid.support.gl20shaders130)
1028         {
1029                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1030                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1031                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1032                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1033                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1034                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1035         }
1036
1037         // the first pretext is which type of shader to compile as
1038         // (later these will all be bound together as a program object)
1039         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1040         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1041         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1042
1043         // the second pretext is the mode (for example a light source)
1044         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1045         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1046         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1047         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1048
1049         // now add all the permutation pretexts
1050         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1051         {
1052                 if (permutation & (1<<i))
1053                 {
1054                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1057                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1058                 }
1059                 else
1060                 {
1061                         // keep line numbers correct
1062                         vertstrings_list[vertstrings_count++] = "\n";
1063                         geomstrings_list[geomstrings_count++] = "\n";
1064                         fragstrings_list[fragstrings_count++] = "\n";
1065                 }
1066         }
1067
1068         // add static parms
1069         R_CompileShader_AddStaticParms(mode, permutation);
1070         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         vertstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         geomstrings_count += shaderstaticparms_count;
1074         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1075         fragstrings_count += shaderstaticparms_count;
1076
1077         // now append the shader text itself
1078         vertstrings_list[vertstrings_count++] = vertexstring;
1079         geomstrings_list[geomstrings_count++] = geometrystring;
1080         fragstrings_list[fragstrings_count++] = fragmentstring;
1081
1082         // if any sources were NULL, clear the respective list
1083         if (!vertexstring)
1084                 vertstrings_count = 0;
1085         if (!geometrystring)
1086                 geomstrings_count = 0;
1087         if (!fragmentstring)
1088                 fragstrings_count = 0;
1089
1090         // compile the shader program
1091         if (vertstrings_count + geomstrings_count + fragstrings_count)
1092                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1093         if (p->program)
1094         {
1095                 CHECKGLERROR
1096                 qglUseProgram(p->program);CHECKGLERROR
1097                 // look up all the uniform variable names we care about, so we don't
1098                 // have to look them up every time we set them
1099
1100                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1101                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1102                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1103                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1104                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1105                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1106                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1107                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1108                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1109                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1110                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1111                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1112                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1113                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1114                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1115                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1116                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1117                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1118                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1119                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1120                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1121                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1122                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1123                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1124                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1125                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1126                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1127                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1128                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1129                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1130                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1131                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1132                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1133                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1134                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1135                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1136                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1137                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1138                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1139                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1140                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1141                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1142                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1143                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1144                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1145                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1146                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1147                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1148                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1149                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1150                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1151                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1152                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1153                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1154                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1155                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1156                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1157                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1158                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1159                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1160                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1161                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1162                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1163                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1164                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1165                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1166                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1167                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1168                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1169                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1170                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1171                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1172                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1173                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1174                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1175                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1176                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1177                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1178                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1179                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1180                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1181                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1182                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1183                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1184                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1185                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1186                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1187                 // initialize the samplers to refer to the texture units we use
1188                 p->tex_Texture_First = -1;
1189                 p->tex_Texture_Second = -1;
1190                 p->tex_Texture_GammaRamps = -1;
1191                 p->tex_Texture_Normal = -1;
1192                 p->tex_Texture_Color = -1;
1193                 p->tex_Texture_Gloss = -1;
1194                 p->tex_Texture_Glow = -1;
1195                 p->tex_Texture_SecondaryNormal = -1;
1196                 p->tex_Texture_SecondaryColor = -1;
1197                 p->tex_Texture_SecondaryGloss = -1;
1198                 p->tex_Texture_SecondaryGlow = -1;
1199                 p->tex_Texture_Pants = -1;
1200                 p->tex_Texture_Shirt = -1;
1201                 p->tex_Texture_FogHeightTexture = -1;
1202                 p->tex_Texture_FogMask = -1;
1203                 p->tex_Texture_Lightmap = -1;
1204                 p->tex_Texture_Deluxemap = -1;
1205                 p->tex_Texture_Attenuation = -1;
1206                 p->tex_Texture_Cube = -1;
1207                 p->tex_Texture_Refraction = -1;
1208                 p->tex_Texture_Reflection = -1;
1209                 p->tex_Texture_ShadowMap2D = -1;
1210                 p->tex_Texture_CubeProjection = -1;
1211                 p->tex_Texture_ScreenDepth = -1;
1212                 p->tex_Texture_ScreenNormalMap = -1;
1213                 p->tex_Texture_ScreenDiffuse = -1;
1214                 p->tex_Texture_ScreenSpecular = -1;
1215                 p->tex_Texture_ReflectMask = -1;
1216                 p->tex_Texture_ReflectCube = -1;
1217                 p->tex_Texture_BounceGrid = -1;
1218                 sampler = 0;
1219                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1220                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1221                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1222                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1223                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1224                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1225                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1227                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1228                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1229                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1230                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1231                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1232                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1233                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1234                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1235                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1236                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1237                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1238                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1239                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1240                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1241                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1242                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1243                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1244                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1245                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1246                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1247                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1248                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1249                 CHECKGLERROR
1250                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1251         }
1252         else
1253                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1254
1255         // free the strings
1256         if (vertexstring)
1257                 Mem_Free(vertexstring);
1258         if (geometrystring)
1259                 Mem_Free(geometrystring);
1260         if (fragmentstring)
1261                 Mem_Free(fragmentstring);
1262 }
1263
1264 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1265 {
1266         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1267         if (r_glsl_permutation != perm)
1268         {
1269                 r_glsl_permutation = perm;
1270                 if (!r_glsl_permutation->program)
1271                 {
1272                         if (!r_glsl_permutation->compiled)
1273                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1274                         if (!r_glsl_permutation->program)
1275                         {
1276                                 // remove features until we find a valid permutation
1277                                 int i;
1278                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1279                                 {
1280                                         // reduce i more quickly whenever it would not remove any bits
1281                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1282                                         if (!(permutation & j))
1283                                                 continue;
1284                                         permutation -= j;
1285                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1286                                         if (!r_glsl_permutation->compiled)
1287                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1288                                         if (r_glsl_permutation->program)
1289                                                 break;
1290                                 }
1291                                 if (i >= SHADERPERMUTATION_COUNT)
1292                                 {
1293                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1294                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1295                                         qglUseProgram(0);CHECKGLERROR
1296                                         return; // no bit left to clear, entire mode is broken
1297                                 }
1298                         }
1299                 }
1300                 CHECKGLERROR
1301                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1302         }
1303         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1304         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1305         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1306 }
1307
1308 #ifdef SUPPORTD3D
1309
1310 #ifdef SUPPORTD3D
1311 #include <d3d9.h>
1312 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1313 extern D3DCAPS9 vid_d3d9caps;
1314 #endif
1315
1316 struct r_hlsl_permutation_s;
1317 typedef struct r_hlsl_permutation_s
1318 {
1319         /// hash lookup data
1320         struct r_hlsl_permutation_s *hashnext;
1321         unsigned int mode;
1322         unsigned int permutation;
1323
1324         /// indicates if we have tried compiling this permutation already
1325         qboolean compiled;
1326         /// NULL if compilation failed
1327         IDirect3DVertexShader9 *vertexshader;
1328         IDirect3DPixelShader9 *pixelshader;
1329 }
1330 r_hlsl_permutation_t;
1331
1332 typedef enum D3DVSREGISTER_e
1333 {
1334         D3DVSREGISTER_TexMatrix = 0, // float4x4
1335         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1336         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1337         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1338         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1339         D3DVSREGISTER_ModelToLight = 20, // float4x4
1340         D3DVSREGISTER_EyePosition = 24,
1341         D3DVSREGISTER_FogPlane = 25,
1342         D3DVSREGISTER_LightDir = 26,
1343         D3DVSREGISTER_LightPosition = 27,
1344 }
1345 D3DVSREGISTER_t;
1346
1347 typedef enum D3DPSREGISTER_e
1348 {
1349         D3DPSREGISTER_Alpha = 0,
1350         D3DPSREGISTER_BloomBlur_Parameters = 1,
1351         D3DPSREGISTER_ClientTime = 2,
1352         D3DPSREGISTER_Color_Ambient = 3,
1353         D3DPSREGISTER_Color_Diffuse = 4,
1354         D3DPSREGISTER_Color_Specular = 5,
1355         D3DPSREGISTER_Color_Glow = 6,
1356         D3DPSREGISTER_Color_Pants = 7,
1357         D3DPSREGISTER_Color_Shirt = 8,
1358         D3DPSREGISTER_DeferredColor_Ambient = 9,
1359         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1360         D3DPSREGISTER_DeferredColor_Specular = 11,
1361         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1362         D3DPSREGISTER_DeferredMod_Specular = 13,
1363         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1364         D3DPSREGISTER_EyePosition = 15, // unused
1365         D3DPSREGISTER_FogColor = 16,
1366         D3DPSREGISTER_FogHeightFade = 17,
1367         D3DPSREGISTER_FogPlane = 18,
1368         D3DPSREGISTER_FogPlaneViewDist = 19,
1369         D3DPSREGISTER_FogRangeRecip = 20,
1370         D3DPSREGISTER_LightColor = 21,
1371         D3DPSREGISTER_LightDir = 22, // unused
1372         D3DPSREGISTER_LightPosition = 23,
1373         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1374         D3DPSREGISTER_PixelSize = 25,
1375         D3DPSREGISTER_ReflectColor = 26,
1376         D3DPSREGISTER_ReflectFactor = 27,
1377         D3DPSREGISTER_ReflectOffset = 28,
1378         D3DPSREGISTER_RefractColor = 29,
1379         D3DPSREGISTER_Saturation = 30,
1380         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1381         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1382         D3DPSREGISTER_ScreenToDepth = 33,
1383         D3DPSREGISTER_ShadowMap_Parameters = 34,
1384         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1385         D3DPSREGISTER_SpecularPower = 36,
1386         D3DPSREGISTER_UserVec1 = 37,
1387         D3DPSREGISTER_UserVec2 = 38,
1388         D3DPSREGISTER_UserVec3 = 39,
1389         D3DPSREGISTER_UserVec4 = 40,
1390         D3DPSREGISTER_ViewTintColor = 41,
1391         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1392         D3DPSREGISTER_BloomColorSubtract = 43,
1393         D3DPSREGISTER_ViewToLight = 44, // float4x4
1394         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1395         D3DPSREGISTER_NormalmapScrollBlend = 52,
1396         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1397         D3DPSREGISTER_OffsetMapping_Bias = 54,
1398         // next at 54
1399 }
1400 D3DPSREGISTER_t;
1401
1402 /// information about each possible shader permutation
1403 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1404 /// currently selected permutation
1405 r_hlsl_permutation_t *r_hlsl_permutation;
1406 /// storage for permutations linked in the hash table
1407 memexpandablearray_t r_hlsl_permutationarray;
1408
1409 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1410 {
1411         //unsigned int hashdepth = 0;
1412         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1413         r_hlsl_permutation_t *p;
1414         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1415         {
1416                 if (p->mode == mode && p->permutation == permutation)
1417                 {
1418                         //if (hashdepth > 10)
1419                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1420                         return p;
1421                 }
1422                 //hashdepth++;
1423         }
1424         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1425         p->mode = mode;
1426         p->permutation = permutation;
1427         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1428         r_hlsl_permutationhash[mode][hashindex] = p;
1429         //if (hashdepth > 10)
1430         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1431         return p;
1432 }
1433
1434 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1435 {
1436         char *shaderstring;
1437         if (!filename || !filename[0])
1438                 return NULL;
1439         if (!strcmp(filename, "hlsl/default.hlsl"))
1440         {
1441                 if (!hlslshaderstring)
1442                 {
1443                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1444                         if (hlslshaderstring)
1445                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1446                         else
1447                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1448                 }
1449                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1450                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1451                 return shaderstring;
1452         }
1453         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1454         if (shaderstring)
1455         {
1456                 if (printfromdisknotice)
1457                         Con_DPrintf("from disk %s... ", filename);
1458                 return shaderstring;
1459         }
1460         return shaderstring;
1461 }
1462
1463 #include <d3dx9.h>
1464 //#include <d3dx9shader.h>
1465 //#include <d3dx9mesh.h>
1466
1467 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1468 {
1469         DWORD *vsbin = NULL;
1470         DWORD *psbin = NULL;
1471         fs_offset_t vsbinsize;
1472         fs_offset_t psbinsize;
1473 //      IDirect3DVertexShader9 *vs = NULL;
1474 //      IDirect3DPixelShader9 *ps = NULL;
1475         ID3DXBuffer *vslog = NULL;
1476         ID3DXBuffer *vsbuffer = NULL;
1477         ID3DXConstantTable *vsconstanttable = NULL;
1478         ID3DXBuffer *pslog = NULL;
1479         ID3DXBuffer *psbuffer = NULL;
1480         ID3DXConstantTable *psconstanttable = NULL;
1481         int vsresult = 0;
1482         int psresult = 0;
1483         char temp[MAX_INPUTLINE];
1484         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1485         qboolean debugshader = gl_paranoid.integer != 0;
1486         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1487         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1488         if (!debugshader)
1489         {
1490                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1491                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1492         }
1493         if ((!vsbin && vertstring) || (!psbin && fragstring))
1494         {
1495                 const char* dllnames_d3dx9 [] =
1496                 {
1497                         "d3dx9_43.dll",
1498                         "d3dx9_42.dll",
1499                         "d3dx9_41.dll",
1500                         "d3dx9_40.dll",
1501                         "d3dx9_39.dll",
1502                         "d3dx9_38.dll",
1503                         "d3dx9_37.dll",
1504                         "d3dx9_36.dll",
1505                         "d3dx9_35.dll",
1506                         "d3dx9_34.dll",
1507                         "d3dx9_33.dll",
1508                         "d3dx9_32.dll",
1509                         "d3dx9_31.dll",
1510                         "d3dx9_30.dll",
1511                         "d3dx9_29.dll",
1512                         "d3dx9_28.dll",
1513                         "d3dx9_27.dll",
1514                         "d3dx9_26.dll",
1515                         "d3dx9_25.dll",
1516                         "d3dx9_24.dll",
1517                         NULL
1518                 };
1519                 dllhandle_t d3dx9_dll = NULL;
1520                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1521                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1522                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1523                 dllfunction_t d3dx9_dllfuncs[] =
1524                 {
1525                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1526                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1527                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1528                         {NULL, NULL}
1529                 };
1530                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1531                 {
1532                         DWORD shaderflags = 0;
1533                         if (debugshader)
1534                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1535                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1536                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1537                         if (vertstring && vertstring[0])
1538                         {
1539                                 if (debugshader)
1540                                 {
1541 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1542 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1543                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1544                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545                                 }
1546                                 else
1547                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1548                                 if (vsbuffer)
1549                                 {
1550                                         vsbinsize = vsbuffer->GetBufferSize();
1551                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1552                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1553                                         vsbuffer->Release();
1554                                 }
1555                                 if (vslog)
1556                                 {
1557                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1558                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1559                                         vslog->Release();
1560                                 }
1561                         }
1562                         if (fragstring && fragstring[0])
1563                         {
1564                                 if (debugshader)
1565                                 {
1566 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1567 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1568                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1569                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570                                 }
1571                                 else
1572                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1573                                 if (psbuffer)
1574                                 {
1575                                         psbinsize = psbuffer->GetBufferSize();
1576                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1577                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1578                                         psbuffer->Release();
1579                                 }
1580                                 if (pslog)
1581                                 {
1582                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1583                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1584                                         pslog->Release();
1585                                 }
1586                         }
1587                         Sys_UnloadLibrary(&d3dx9_dll);
1588                 }
1589                 else
1590                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1591         }
1592         if (vsbin && psbin)
1593         {
1594                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1595                 if (FAILED(vsresult))
1596                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1597                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1598                 if (FAILED(psresult))
1599                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1600         }
1601         // free the shader data
1602         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1603         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1604 }
1605
1606 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1607 {
1608         int i;
1609         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1610         int vertstring_length = 0;
1611         int geomstring_length = 0;
1612         int fragstring_length = 0;
1613         char *t;
1614         char *vertexstring, *geometrystring, *fragmentstring;
1615         char *vertstring, *geomstring, *fragstring;
1616         char permutationname[256];
1617         char cachename[256];
1618         int vertstrings_count = 0;
1619         int geomstrings_count = 0;
1620         int fragstrings_count = 0;
1621         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1622         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1623         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1624
1625         if (p->compiled)
1626                 return;
1627         p->compiled = true;
1628         p->vertexshader = NULL;
1629         p->pixelshader = NULL;
1630
1631         permutationname[0] = 0;
1632         cachename[0] = 0;
1633         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1634         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1635         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1636
1637         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1638         strlcat(cachename, "hlsl/", sizeof(cachename));
1639
1640         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1641         vertstrings_count = 0;
1642         geomstrings_count = 0;
1643         fragstrings_count = 0;
1644         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1645         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1646         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1647
1648         // the first pretext is which type of shader to compile as
1649         // (later these will all be bound together as a program object)
1650         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1651         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1652         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1653
1654         // the second pretext is the mode (for example a light source)
1655         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1656         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1657         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1658         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1659         strlcat(cachename, modeinfo->name, sizeof(cachename));
1660
1661         // now add all the permutation pretexts
1662         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1663         {
1664                 if (permutation & (1<<i))
1665                 {
1666                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1667                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1668                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1669                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1670                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1671                 }
1672                 else
1673                 {
1674                         // keep line numbers correct
1675                         vertstrings_list[vertstrings_count++] = "\n";
1676                         geomstrings_list[geomstrings_count++] = "\n";
1677                         fragstrings_list[fragstrings_count++] = "\n";
1678                 }
1679         }
1680
1681         // add static parms
1682         R_CompileShader_AddStaticParms(mode, permutation);
1683         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         vertstrings_count += shaderstaticparms_count;
1685         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1686         geomstrings_count += shaderstaticparms_count;
1687         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1688         fragstrings_count += shaderstaticparms_count;
1689
1690         // replace spaces in the cachename with _ characters
1691         for (i = 0;cachename[i];i++)
1692                 if (cachename[i] == ' ')
1693                         cachename[i] = '_';
1694
1695         // now append the shader text itself
1696         vertstrings_list[vertstrings_count++] = vertexstring;
1697         geomstrings_list[geomstrings_count++] = geometrystring;
1698         fragstrings_list[fragstrings_count++] = fragmentstring;
1699
1700         // if any sources were NULL, clear the respective list
1701         if (!vertexstring)
1702                 vertstrings_count = 0;
1703         if (!geometrystring)
1704                 geomstrings_count = 0;
1705         if (!fragmentstring)
1706                 fragstrings_count = 0;
1707
1708         vertstring_length = 0;
1709         for (i = 0;i < vertstrings_count;i++)
1710                 vertstring_length += strlen(vertstrings_list[i]);
1711         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1712         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1713                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1714
1715         geomstring_length = 0;
1716         for (i = 0;i < geomstrings_count;i++)
1717                 geomstring_length += strlen(geomstrings_list[i]);
1718         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1719         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1720                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1721
1722         fragstring_length = 0;
1723         for (i = 0;i < fragstrings_count;i++)
1724                 fragstring_length += strlen(fragstrings_list[i]);
1725         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1726         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1727                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1728
1729         // try to load the cached shader, or generate one
1730         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1731
1732         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1733                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1734         else
1735                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1736
1737         // free the strings
1738         if (vertstring)
1739                 Mem_Free(vertstring);
1740         if (geomstring)
1741                 Mem_Free(geomstring);
1742         if (fragstring)
1743                 Mem_Free(fragstring);
1744         if (vertexstring)
1745                 Mem_Free(vertexstring);
1746         if (geometrystring)
1747                 Mem_Free(geometrystring);
1748         if (fragmentstring)
1749                 Mem_Free(fragmentstring);
1750 }
1751
1752 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1753 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1754 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);}
1755 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);}
1756 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);}
1757 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);}
1758
1759 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1760 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1761 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);}
1762 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);}
1763 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);}
1764 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);}
1765
1766 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1767 {
1768         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1769         if (r_hlsl_permutation != perm)
1770         {
1771                 r_hlsl_permutation = perm;
1772                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                 {
1774                         if (!r_hlsl_permutation->compiled)
1775                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1777                         {
1778                                 // remove features until we find a valid permutation
1779                                 int i;
1780                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1781                                 {
1782                                         // reduce i more quickly whenever it would not remove any bits
1783                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1784                                         if (!(permutation & j))
1785                                                 continue;
1786                                         permutation -= j;
1787                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1788                                         if (!r_hlsl_permutation->compiled)
1789                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1790                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1791                                                 break;
1792                                 }
1793                                 if (i >= SHADERPERMUTATION_COUNT)
1794                                 {
1795                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1796                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1797                                         return; // no bit left to clear, entire mode is broken
1798                                 }
1799                         }
1800                 }
1801                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1802                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1803         }
1804         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1805         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1806         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1807 }
1808 #endif
1809
1810 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1811 {
1812         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1813         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1814         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1815         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1816 }
1817
1818 void R_GLSL_Restart_f(void)
1819 {
1820         unsigned int i, limit;
1821         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1822                 Mem_Free(glslshaderstring);
1823         glslshaderstring = NULL;
1824         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1825                 Mem_Free(hlslshaderstring);
1826         hlslshaderstring = NULL;
1827         switch(vid.renderpath)
1828         {
1829         case RENDERPATH_D3D9:
1830 #ifdef SUPPORTD3D
1831                 {
1832                         r_hlsl_permutation_t *p;
1833                         r_hlsl_permutation = NULL;
1834                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1835                         for (i = 0;i < limit;i++)
1836                         {
1837                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1838                                 {
1839                                         if (p->vertexshader)
1840                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1841                                         if (p->pixelshader)
1842                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1843                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1844                                 }
1845                         }
1846                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1847                 }
1848 #endif
1849                 break;
1850         case RENDERPATH_D3D10:
1851                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_D3D11:
1854                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1855                 break;
1856         case RENDERPATH_GL20:
1857         case RENDERPATH_GLES2:
1858                 {
1859                         r_glsl_permutation_t *p;
1860                         r_glsl_permutation = NULL;
1861                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1862                         for (i = 0;i < limit;i++)
1863                         {
1864                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1865                                 {
1866                                         GL_Backend_FreeProgram(p->program);
1867                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1868                                 }
1869                         }
1870                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1871                 }
1872                 break;
1873         case RENDERPATH_GL11:
1874         case RENDERPATH_GL13:
1875         case RENDERPATH_GLES1:
1876                 break;
1877         case RENDERPATH_SOFT:
1878                 break;
1879         }
1880 }
1881
1882 void R_GLSL_DumpShader_f(void)
1883 {
1884         int i;
1885         qfile_t *file;
1886
1887         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1888         if (file)
1889         {
1890                 FS_Print(file, "/* The engine may define the following macros:\n");
1891                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1892                 for (i = 0;i < SHADERMODE_COUNT;i++)
1893                         FS_Print(file, glslshadermodeinfo[i].pretext);
1894                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1895                         FS_Print(file, shaderpermutationinfo[i].pretext);
1896                 FS_Print(file, "*/\n");
1897                 FS_Print(file, builtinshaderstring);
1898                 FS_Close(file);
1899                 Con_Printf("glsl/default.glsl written\n");
1900         }
1901         else
1902                 Con_Printf("failed to write to glsl/default.glsl\n");
1903
1904         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1905         if (file)
1906         {
1907                 FS_Print(file, "/* The engine may define the following macros:\n");
1908                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1909                 for (i = 0;i < SHADERMODE_COUNT;i++)
1910                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1911                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1912                         FS_Print(file, shaderpermutationinfo[i].pretext);
1913                 FS_Print(file, "*/\n");
1914                 FS_Print(file, builtinhlslshaderstring);
1915                 FS_Close(file);
1916                 Con_Printf("hlsl/default.hlsl written\n");
1917         }
1918         else
1919                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1920 }
1921
1922 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1923 {
1924         unsigned int permutation = 0;
1925         if (r_trippy.integer && !notrippy)
1926                 permutation |= SHADERPERMUTATION_TRIPPY;
1927         permutation |= SHADERPERMUTATION_VIEWTINT;
1928         if (first)
1929                 permutation |= SHADERPERMUTATION_DIFFUSE;
1930         if (second)
1931                 permutation |= SHADERPERMUTATION_SPECULAR;
1932         if (texturemode == GL_MODULATE)
1933                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1934         else if (texturemode == GL_ADD)
1935                 permutation |= SHADERPERMUTATION_GLOW;
1936         else if (texturemode == GL_DECAL)
1937                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1938         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1939                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1940         if (!second)
1941                 texturemode = GL_MODULATE;
1942         if (vid.allowalphatocoverage)
1943                 GL_AlphaToCoverage(false);
1944         switch (vid.renderpath)
1945         {
1946         case RENDERPATH_D3D9:
1947 #ifdef SUPPORTD3D
1948                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1949                 R_Mesh_TexBind(GL20TU_FIRST , first );
1950                 R_Mesh_TexBind(GL20TU_SECOND, second);
1951                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1952                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1953 #endif
1954                 break;
1955         case RENDERPATH_D3D10:
1956                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1957                 break;
1958         case RENDERPATH_D3D11:
1959                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_GL20:
1962         case RENDERPATH_GLES2:
1963                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1965                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1966                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1967                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1968                 break;
1969         case RENDERPATH_GL13:
1970         case RENDERPATH_GLES1:
1971                 R_Mesh_TexBind(0, first );
1972                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1973                 R_Mesh_TexBind(1, second);
1974                 if (second)
1975                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1976                 break;
1977         case RENDERPATH_GL11:
1978                 R_Mesh_TexBind(0, first );
1979                 break;
1980         case RENDERPATH_SOFT:
1981                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1982                 R_Mesh_TexBind(GL20TU_FIRST , first );
1983                 R_Mesh_TexBind(GL20TU_SECOND, second);
1984                 break;
1985         }
1986 }
1987
1988 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1989 {
1990         unsigned int permutation = 0;
1991         if (r_trippy.integer && !notrippy)
1992                 permutation |= SHADERPERMUTATION_TRIPPY;
1993         if (vid.allowalphatocoverage)
1994                 GL_AlphaToCoverage(false);
1995         switch (vid.renderpath)
1996         {
1997         case RENDERPATH_D3D9:
1998 #ifdef SUPPORTD3D
1999                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2000 #endif
2001                 break;
2002         case RENDERPATH_D3D10:
2003                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2004                 break;
2005         case RENDERPATH_D3D11:
2006                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2007                 break;
2008         case RENDERPATH_GL20:
2009         case RENDERPATH_GLES2:
2010                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2011                 break;
2012         case RENDERPATH_GL13:
2013         case RENDERPATH_GLES1:
2014                 R_Mesh_TexBind(0, 0);
2015                 R_Mesh_TexBind(1, 0);
2016                 break;
2017         case RENDERPATH_GL11:
2018                 R_Mesh_TexBind(0, 0);
2019                 break;
2020         case RENDERPATH_SOFT:
2021                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2022                 break;
2023         }
2024 }
2025
2026 void R_SetupShader_ShowDepth(qboolean notrippy)
2027 {
2028         int permutation = 0;
2029         if (r_trippy.integer && !notrippy)
2030                 permutation |= SHADERPERMUTATION_TRIPPY;
2031         if (vid.allowalphatocoverage)
2032                 GL_AlphaToCoverage(false);
2033         switch (vid.renderpath)
2034         {
2035         case RENDERPATH_D3D9:
2036 #ifdef SUPPORTHLSL
2037                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2038 #endif
2039                 break;
2040         case RENDERPATH_D3D10:
2041                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2042                 break;
2043         case RENDERPATH_D3D11:
2044                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2045                 break;
2046         case RENDERPATH_GL20:
2047         case RENDERPATH_GLES2:
2048                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2049                 break;
2050         case RENDERPATH_GL13:
2051         case RENDERPATH_GLES1:
2052                 break;
2053         case RENDERPATH_GL11:
2054                 break;
2055         case RENDERPATH_SOFT:
2056                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2057                 break;
2058         }
2059 }
2060
2061 extern qboolean r_shadow_usingdeferredprepass;
2062 extern cvar_t r_shadow_deferred_8bitrange;
2063 extern rtexture_t *r_shadow_attenuationgradienttexture;
2064 extern rtexture_t *r_shadow_attenuation2dtexture;
2065 extern rtexture_t *r_shadow_attenuation3dtexture;
2066 extern qboolean r_shadow_usingshadowmap2d;
2067 extern qboolean r_shadow_usingshadowmaportho;
2068 extern float r_shadow_shadowmap_texturescale[2];
2069 extern float r_shadow_shadowmap_parameters[4];
2070 extern qboolean r_shadow_shadowmapvsdct;
2071 extern qboolean r_shadow_shadowmapsampler;
2072 extern int r_shadow_shadowmappcf;
2073 extern rtexture_t *r_shadow_shadowmap2dtexture;
2074 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2075 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2076 extern matrix4x4_t r_shadow_shadowmapmatrix;
2077 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2078 extern int r_shadow_prepass_width;
2079 extern int r_shadow_prepass_height;
2080 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2081 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2082 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2083 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2084 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2085
2086 #define BLENDFUNC_ALLOWS_COLORMOD      1
2087 #define BLENDFUNC_ALLOWS_FOG           2
2088 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2089 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2090 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2091 static int R_BlendFuncFlags(int src, int dst)
2092 {
2093         int r = 0;
2094
2095         // a blendfunc allows colormod if:
2096         // a) it can never keep the destination pixel invariant, or
2097         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2098         // this is to prevent unintended side effects from colormod
2099
2100         // a blendfunc allows fog if:
2101         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2102         // this is to prevent unintended side effects from fog
2103
2104         // these checks are the output of fogeval.pl
2105
2106         r |= BLENDFUNC_ALLOWS_COLORMOD;
2107         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2108         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2109         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2110         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2115         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2116         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2119         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2123         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2128
2129         return r;
2130 }
2131
2132 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)
2133 {
2134         // select a permutation of the lighting shader appropriate to this
2135         // combination of texture, entity, light source, and fogging, only use the
2136         // minimum features necessary to avoid wasting rendering time in the
2137         // fragment shader on features that are not being used
2138         unsigned int permutation = 0;
2139         unsigned int mode = 0;
2140         int blendfuncflags;
2141         static float dummy_colormod[3] = {1, 1, 1};
2142         float *colormod = rsurface.colormod;
2143         float m16f[16];
2144         matrix4x4_t tempmatrix;
2145         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2146         if (r_trippy.integer && !notrippy)
2147                 permutation |= SHADERPERMUTATION_TRIPPY;
2148         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2149                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2150         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2151                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2152         if (rsurfacepass == RSURFPASS_BACKGROUND)
2153         {
2154                 // distorted background
2155                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2156                 {
2157                         mode = SHADERMODE_WATER;
2158                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2159                         {
2160                                 // this is the right thing to do for wateralpha
2161                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2162                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2163                         }
2164                         else
2165                         {
2166                                 // this is the right thing to do for entity alpha
2167                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2168                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2169                         }
2170                 }
2171                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2172                 {
2173                         mode = SHADERMODE_REFRACTION;
2174                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2175                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2176                 }
2177                 else
2178                 {
2179                         mode = SHADERMODE_GENERIC;
2180                         permutation |= SHADERPERMUTATION_DIFFUSE;
2181                         GL_BlendFunc(GL_ONE, GL_ZERO);
2182                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2183                 }
2184                 if (vid.allowalphatocoverage)
2185                         GL_AlphaToCoverage(false);
2186         }
2187         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2188         {
2189                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 // normalmap (deferred prepass), may use alpha test on diffuse
2202                 mode = SHADERMODE_DEFERREDGEOMETRY;
2203                 GL_BlendFunc(GL_ONE, GL_ZERO);
2204                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2205                 if (vid.allowalphatocoverage)
2206                         GL_AlphaToCoverage(false);
2207         }
2208         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2209         {
2210                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2211                 {
2212                         switch(rsurface.texture->offsetmapping)
2213                         {
2214                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2215                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2216                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2217                         case OFFSETMAPPING_OFF: break;
2218                         }
2219                 }
2220                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2221                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2222                 // light source
2223                 mode = SHADERMODE_LIGHTSOURCE;
2224                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2225                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2226                 if (diffusescale > 0)
2227                         permutation |= SHADERPERMUTATION_DIFFUSE;
2228                 if (specularscale > 0)
2229                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2230                 if (r_refdef.fogenabled)
2231                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2232                 if (rsurface.texture->colormapping)
2233                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2234                 if (r_shadow_usingshadowmap2d)
2235                 {
2236                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2237                         if(r_shadow_shadowmapvsdct)
2238                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2239
2240                         if (r_shadow_shadowmapsampler)
2241                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2242                         if (r_shadow_shadowmappcf > 1)
2243                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2244                         else if (r_shadow_shadowmappcf)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2246                 }
2247                 if (rsurface.texture->reflectmasktexture)
2248                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2249                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2250                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2251                 if (vid.allowalphatocoverage)
2252                         GL_AlphaToCoverage(false);
2253         }
2254         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2255         {
2256                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2257                 {
2258                         switch(rsurface.texture->offsetmapping)
2259                         {
2260                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2261                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2262                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2263                         case OFFSETMAPPING_OFF: break;
2264                         }
2265                 }
2266                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2267                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2268                 // unshaded geometry (fullbright or ambient model lighting)
2269                 mode = SHADERMODE_FLATCOLOR;
2270                 ambientscale = diffusescale = specularscale = 0;
2271                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2272                         permutation |= SHADERPERMUTATION_GLOW;
2273                 if (r_refdef.fogenabled)
2274                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2275                 if (rsurface.texture->colormapping)
2276                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2277                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2278                 {
2279                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2280                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2281
2282                         if (r_shadow_shadowmapsampler)
2283                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2284                         if (r_shadow_shadowmappcf > 1)
2285                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2286                         else if (r_shadow_shadowmappcf)
2287                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2290                         permutation |= SHADERPERMUTATION_REFLECTION;
2291                 if (rsurface.texture->reflectmasktexture)
2292                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2293                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2294                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295                 // when using alphatocoverage, we don't need alphakill
2296                 if (vid.allowalphatocoverage)
2297                 {
2298                         if (r_transparent_alphatocoverage.integer)
2299                         {
2300                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2301                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2302                         }
2303                         else
2304                                 GL_AlphaToCoverage(false);
2305                 }
2306         }
2307         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2308         {
2309                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2310                 {
2311                         switch(rsurface.texture->offsetmapping)
2312                         {
2313                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2314                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2315                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_OFF: break;
2317                         }
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2320                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2321                 // directional model lighting
2322                 mode = SHADERMODE_LIGHTDIRECTION;
2323                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2324                         permutation |= SHADERPERMUTATION_GLOW;
2325                 permutation |= SHADERPERMUTATION_DIFFUSE;
2326                 if (specularscale > 0)
2327                         permutation |= SHADERPERMUTATION_SPECULAR;
2328                 if (r_refdef.fogenabled)
2329                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2330                 if (rsurface.texture->colormapping)
2331                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2332                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2333                 {
2334                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2335                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2336
2337                         if (r_shadow_shadowmapsampler)
2338                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2339                         if (r_shadow_shadowmappcf > 1)
2340                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2341                         else if (r_shadow_shadowmappcf)
2342                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2347                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348                 if (rsurface.texture->reflectmasktexture)
2349                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2351                 {
2352                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2353                         if (r_shadow_bouncegriddirectional)
2354                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2355                 }
2356                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358                 // when using alphatocoverage, we don't need alphakill
2359                 if (vid.allowalphatocoverage)
2360                 {
2361                         if (r_transparent_alphatocoverage.integer)
2362                         {
2363                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2364                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2365                         }
2366                         else
2367                                 GL_AlphaToCoverage(false);
2368                 }
2369         }
2370         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2371         {
2372                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2373                 {
2374                         switch(rsurface.texture->offsetmapping)
2375                         {
2376                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2377                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_OFF: break;
2380                         }
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2383                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2384                 // ambient model lighting
2385                 mode = SHADERMODE_LIGHTDIRECTION;
2386                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2387                         permutation |= SHADERPERMUTATION_GLOW;
2388                 if (r_refdef.fogenabled)
2389                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2390                 if (rsurface.texture->colormapping)
2391                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2392                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2393                 {
2394                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2395                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2396
2397                         if (r_shadow_shadowmapsampler)
2398                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2399                         if (r_shadow_shadowmappcf > 1)
2400                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2401                         else if (r_shadow_shadowmappcf)
2402                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2403                 }
2404                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2405                         permutation |= SHADERPERMUTATION_REFLECTION;
2406                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2407                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2408                 if (rsurface.texture->reflectmasktexture)
2409                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2410                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2411                 {
2412                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2413                         if (r_shadow_bouncegriddirectional)
2414                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2415                 }
2416                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2417                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2418                 // when using alphatocoverage, we don't need alphakill
2419                 if (vid.allowalphatocoverage)
2420                 {
2421                         if (r_transparent_alphatocoverage.integer)
2422                         {
2423                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2424                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2425                         }
2426                         else
2427                                 GL_AlphaToCoverage(false);
2428                 }
2429         }
2430         else
2431         {
2432                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2433                 {
2434                         switch(rsurface.texture->offsetmapping)
2435                         {
2436                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2437                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2438                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2439                         case OFFSETMAPPING_OFF: break;
2440                         }
2441                 }
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2443                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2444                 // lightmapped wall
2445                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446                         permutation |= SHADERPERMUTATION_GLOW;
2447                 if (r_refdef.fogenabled)
2448                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449                 if (rsurface.texture->colormapping)
2450                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2451                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452                 {
2453                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455
2456                         if (r_shadow_shadowmapsampler)
2457                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2458                         if (r_shadow_shadowmappcf > 1)
2459                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2460                         else if (r_shadow_shadowmappcf)
2461                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2462                 }
2463                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2464                         permutation |= SHADERPERMUTATION_REFLECTION;
2465                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2466                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2467                 if (rsurface.texture->reflectmasktexture)
2468                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2469                 if (FAKELIGHT_ENABLED)
2470                 {
2471                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2472                         mode = SHADERMODE_FAKELIGHT;
2473                         permutation |= SHADERPERMUTATION_DIFFUSE;
2474                         if (specularscale > 0)
2475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476                 }
2477                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2478                 {
2479                         // deluxemapping (light direction texture)
2480                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2481                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2482                         else
2483                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2484                         permutation |= SHADERPERMUTATION_DIFFUSE;
2485                         if (specularscale > 0)
2486                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2487                 }
2488                 else if (r_glsl_deluxemapping.integer >= 2)
2489                 {
2490                         // fake deluxemapping (uniform light direction in tangentspace)
2491                         if (rsurface.uselightmaptexture)
2492                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2493                         else
2494                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2495                         permutation |= SHADERPERMUTATION_DIFFUSE;
2496                         if (specularscale > 0)
2497                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2498                 }
2499                 else if (rsurface.uselightmaptexture)
2500                 {
2501                         // ordinary lightmapping (q1bsp, q3bsp)
2502                         mode = SHADERMODE_LIGHTMAP;
2503                 }
2504                 else
2505                 {
2506                         // ordinary vertex coloring (q3bsp)
2507                         mode = SHADERMODE_VERTEXCOLOR;
2508                 }
2509                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2510                 {
2511                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2512                         if (r_shadow_bouncegriddirectional)
2513                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2514                 }
2515                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2516                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2517                 // when using alphatocoverage, we don't need alphakill
2518                 if (vid.allowalphatocoverage)
2519                 {
2520                         if (r_transparent_alphatocoverage.integer)
2521                         {
2522                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2523                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2524                         }
2525                         else
2526                                 GL_AlphaToCoverage(false);
2527                 }
2528         }
2529         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2530                 colormod = dummy_colormod;
2531         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2532                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2533         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2534                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2535         switch(vid.renderpath)
2536         {
2537         case RENDERPATH_D3D9:
2538 #ifdef SUPPORTD3D
2539                 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);
2540                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2541                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2542                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2543                 if (mode == SHADERMODE_LIGHTSOURCE)
2544                 {
2545                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2546                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2547                 }
2548                 else
2549                 {
2550                         if (mode == SHADERMODE_LIGHTDIRECTION)
2551                         {
2552                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2553                         }
2554                 }
2555                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2556                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2557                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2558                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2559                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2560
2561                 if (mode == SHADERMODE_LIGHTSOURCE)
2562                 {
2563                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2564                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2565                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2566                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2567                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2568
2569                         // additive passes are only darkened by fog, not tinted
2570                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2571                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2572                 }
2573                 else
2574                 {
2575                         if (mode == SHADERMODE_FLATCOLOR)
2576                         {
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2578                         }
2579                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2580                         {
2581                                 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]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2583                                 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);
2584                                 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);
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2588                         }
2589                         else
2590                         {
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2592                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2593                                 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);
2594                                 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);
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2596                         }
2597                         // additive passes are only darkened by fog, not tinted
2598                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2599                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2600                         else
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2602                         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);
2603                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2604                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2605                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2606                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2607                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2608                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2609                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2610                         if (mode == SHADERMODE_WATER)
2611                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2612                 }
2613                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2614                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2615                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2616                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2617                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2618                 if (rsurface.texture->pantstexture)
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2620                 else
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2622                 if (rsurface.texture->shirttexture)
2623                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2624                 else
2625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2626                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2627                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2628                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2629                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2630                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2631                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2632                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2633                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2634                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2635                         );
2636                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2637                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2638                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2639                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2640
2641                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2642                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2643                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2644                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2645                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2646                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2648                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2649                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2650                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2651                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2652                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2653                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2654                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2655                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2656                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2657                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2658                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2659                 {
2660                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2661                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2662                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2663                 }
2664                 else
2665                 {
2666                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2667                 }
2668 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2669 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2670                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2671                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2672                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2673                 {
2674                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2675                         if (rsurface.rtlight)
2676                         {
2677                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2678                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2679                         }
2680                 }
2681 #endif
2682                 break;
2683         case RENDERPATH_D3D10:
2684                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2685                 break;
2686         case RENDERPATH_D3D11:
2687                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2688                 break;
2689         case RENDERPATH_GL20:
2690         case RENDERPATH_GLES2:
2691                 if (!vid.useinterleavedarrays)
2692                 {
2693                         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);
2694                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2695                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2696                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2701                 }
2702                 else
2703                 {
2704                         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);
2705                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2706                 }
2707                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2708                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2709                 if (mode == SHADERMODE_LIGHTSOURCE)
2710                 {
2711                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2712                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2713                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2714                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2715                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2716                         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);
2717         
2718                         // additive passes are only darkened by fog, not tinted
2719                         if (r_glsl_permutation->loc_FogColor >= 0)
2720                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2721                         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);
2722                 }
2723                 else
2724                 {
2725                         if (mode == SHADERMODE_FLATCOLOR)
2726                         {
2727                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2728                         }
2729                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2730                         {
2731                                 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]);
2732                                 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]);
2733                                 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);
2734                                 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);
2735                                 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);
2736                                 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]);
2737                                 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]);
2738                         }
2739                         else
2740                         {
2741                                 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]);
2742                                 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]);
2743                                 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);
2744                                 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);
2745                                 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);
2746                         }
2747                         // additive passes are only darkened by fog, not tinted
2748                         if (r_glsl_permutation->loc_FogColor >= 0)
2749                         {
2750                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2751                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2752                                 else
2753                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2754                         }
2755                         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);
2756                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2757                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2758                         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]);
2759                         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]);
2760                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2761                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2762                         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);
2763                         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]);
2764                 }
2765                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2766                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2767                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2768                 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]);
2769                 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]);
2770
2771                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2772                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2773                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2774                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2775                 {
2776                         if (rsurface.texture->pantstexture)
2777                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2778                         else
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2780                 }
2781                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2782                 {
2783                         if (rsurface.texture->shirttexture)
2784                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2785                         else
2786                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2787                 }
2788                 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]);
2789                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2790                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2791                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2792                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2793                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2794                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2795                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2796                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2797                         );
2798                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2799                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2800                 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]);
2801                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2802                 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);}
2803                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2804
2805                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2806                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2807                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2808                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2809                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2810                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2811                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2812                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2813                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2814                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2815                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2816                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2817                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2818                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2819                 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);
2820                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2821                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2822                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2823                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2824                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2825                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2826                 {
2827                         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);
2828                         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);
2829                         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);
2830                 }
2831                 else
2832                 {
2833                         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);
2834                 }
2835                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2836                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2837                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2838                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2839                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2840                 {
2841                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2842                         if (rsurface.rtlight)
2843                         {
2844                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2845                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2846                         }
2847                 }
2848                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2849                 CHECKGLERROR
2850                 break;
2851         case RENDERPATH_GL11:
2852         case RENDERPATH_GL13:
2853         case RENDERPATH_GLES1:
2854                 break;
2855         case RENDERPATH_SOFT:
2856                 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);
2857                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2858                 R_SetupShader_SetPermutationSoft(mode, permutation);
2859                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2860                 if (mode == SHADERMODE_LIGHTSOURCE)
2861                 {
2862                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2865                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2866                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2867                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2868         
2869                         // additive passes are only darkened by fog, not tinted
2870                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2872                 }
2873                 else
2874                 {
2875                         if (mode == SHADERMODE_FLATCOLOR)
2876                         {
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2878                         }
2879                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2880                         {
2881                                 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]);
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2883                                 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);
2884                                 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);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2886                                 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]);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2888                         }
2889                         else
2890                         {
2891                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2893                                 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);
2894                                 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);
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2896                         }
2897                         // additive passes are only darkened by fog, not tinted
2898                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2902                         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);
2903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2905                         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]);
2906                         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]);
2907                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2908                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2909                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2910                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2911                 }
2912                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2913                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2914                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2915                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2916                 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]);
2917
2918                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2920                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2921                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2922                 {
2923                         if (rsurface.texture->pantstexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2927                 }
2928                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2929                 {
2930                         if (rsurface.texture->shirttexture)
2931                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2932                         else
2933                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2934                 }
2935                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2936                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2937                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2938                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2939                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2940                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2941                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2942                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2943                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2944                         );
2945                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2946                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2947                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2948                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2949
2950                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2951                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2952                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2953                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2954                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2955                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2956                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2957                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2958                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2959                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2960                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2961                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2962                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2963                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2964                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2965                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2966                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2967                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2968                 {
2969                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2970                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2971                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2972                 }
2973                 else
2974                 {
2975                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2976                 }
2977 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2978 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2979                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2980                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2981                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2982                 {
2983                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2984                         if (rsurface.rtlight)
2985                         {
2986                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2987                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2988                         }
2989                 }
2990                 break;
2991         }
2992 }
2993
2994 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2995 {
2996         // select a permutation of the lighting shader appropriate to this
2997         // combination of texture, entity, light source, and fogging, only use the
2998         // minimum features necessary to avoid wasting rendering time in the
2999         // fragment shader on features that are not being used
3000         unsigned int permutation = 0;
3001         unsigned int mode = 0;
3002         const float *lightcolorbase = rtlight->currentcolor;
3003         float ambientscale = rtlight->ambientscale;
3004         float diffusescale = rtlight->diffusescale;
3005         float specularscale = rtlight->specularscale;
3006         // this is the location of the light in view space
3007         vec3_t viewlightorigin;
3008         // this transforms from view space (camera) to light space (cubemap)
3009         matrix4x4_t viewtolight;
3010         matrix4x4_t lighttoview;
3011         float viewtolight16f[16];
3012         float range = 1.0f / r_shadow_deferred_8bitrange.value;
3013         // light source
3014         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3015         if (rtlight->currentcubemap != r_texture_whitecube)
3016                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3017         if (diffusescale > 0)
3018                 permutation |= SHADERPERMUTATION_DIFFUSE;
3019         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3020                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3021         if (r_shadow_usingshadowmap2d)
3022         {
3023                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3024                 if (r_shadow_shadowmapvsdct)
3025                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3026
3027                 if (r_shadow_shadowmapsampler)
3028                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3029                 if (r_shadow_shadowmappcf > 1)
3030                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3031                 else if (r_shadow_shadowmappcf)
3032                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3033         }
3034         if (vid.allowalphatocoverage)
3035                 GL_AlphaToCoverage(false);
3036         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3037         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3038         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3039         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3040         switch(vid.renderpath)
3041         {
3042         case RENDERPATH_D3D9:
3043 #ifdef SUPPORTD3D
3044                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3045                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3046                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3047                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3048                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3049                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3050                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3051                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3052                 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);
3053                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3054                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3055
3056                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3057                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3058                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3059                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3060                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3061                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3062 #endif
3063                 break;
3064         case RENDERPATH_D3D10:
3065                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3066                 break;
3067         case RENDERPATH_D3D11:
3068                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3069                 break;
3070         case RENDERPATH_GL20:
3071         case RENDERPATH_GLES2:
3072                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3073                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3074                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3075                 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);
3076                 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);
3077                 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);
3078                 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]);
3079                 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]);
3080                 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);
3081                 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]);
3082                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3083
3084                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3085                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3086                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3087                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3088                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3089                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3090                 break;
3091         case RENDERPATH_GL11:
3092         case RENDERPATH_GL13:
3093         case RENDERPATH_GLES1:
3094                 break;
3095         case RENDERPATH_SOFT:
3096                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3097                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3098                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3099                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3100                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3101                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3102                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3103                 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]);
3104                 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);
3105                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3106                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3107
3108                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3109                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3110                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3111                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3112                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3113                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3114                 break;
3115         }
3116 }
3117
3118 #define SKINFRAME_HASH 1024
3119
3120 typedef struct
3121 {
3122         int loadsequence; // incremented each level change
3123         memexpandablearray_t array;
3124         skinframe_t *hash[SKINFRAME_HASH];
3125 }
3126 r_skinframe_t;
3127 r_skinframe_t r_skinframe;
3128
3129 void R_SkinFrame_PrepareForPurge(void)
3130 {
3131         r_skinframe.loadsequence++;
3132         // wrap it without hitting zero
3133         if (r_skinframe.loadsequence >= 200)
3134                 r_skinframe.loadsequence = 1;
3135 }
3136
3137 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3138 {
3139         if (!skinframe)
3140                 return;
3141         // mark the skinframe as used for the purging code
3142         skinframe->loadsequence = r_skinframe.loadsequence;
3143 }
3144
3145 void R_SkinFrame_Purge(void)
3146 {
3147         int i;
3148         skinframe_t *s;
3149         for (i = 0;i < SKINFRAME_HASH;i++)
3150         {
3151                 for (s = r_skinframe.hash[i];s;s = s->next)
3152                 {
3153                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3154                         {
3155                                 if (s->merged == s->base)
3156                                         s->merged = NULL;
3157                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3158                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3159                                 R_PurgeTexture(s->merged);s->merged = NULL;
3160                                 R_PurgeTexture(s->base  );s->base   = NULL;
3161                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3162                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3163                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3164                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3165                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3166                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3167                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3168                                 s->loadsequence = 0;
3169                         }
3170                 }
3171         }
3172 }
3173
3174 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3175         skinframe_t *item;
3176         char basename[MAX_QPATH];
3177
3178         Image_StripImageExtension(name, basename, sizeof(basename));
3179
3180         if( last == NULL ) {
3181                 int hashindex;
3182                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3183                 item = r_skinframe.hash[hashindex];
3184         } else {
3185                 item = last->next;
3186         }
3187
3188         // linearly search through the hash bucket
3189         for( ; item ; item = item->next ) {
3190                 if( !strcmp( item->basename, basename ) ) {
3191                         return item;
3192                 }
3193         }
3194         return NULL;
3195 }
3196
3197 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3198 {
3199         skinframe_t *item;
3200         int hashindex;
3201         char basename[MAX_QPATH];
3202
3203         Image_StripImageExtension(name, basename, sizeof(basename));
3204
3205         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3206         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3207                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3208                         break;
3209
3210         if (!item) {
3211                 rtexture_t *dyntexture;
3212                 // check whether its a dynamic texture
3213                 dyntexture = CL_GetDynTexture( basename );
3214                 if (!add && !dyntexture)
3215                         return NULL;
3216                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3217                 memset(item, 0, sizeof(*item));
3218                 strlcpy(item->basename, basename, sizeof(item->basename));
3219                 item->base = dyntexture; // either NULL or dyntexture handle
3220                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3221                 item->comparewidth = comparewidth;
3222                 item->compareheight = compareheight;
3223                 item->comparecrc = comparecrc;
3224                 item->next = r_skinframe.hash[hashindex];
3225                 r_skinframe.hash[hashindex] = item;
3226         }
3227         else if (textureflags & TEXF_FORCE_RELOAD)
3228         {
3229                 rtexture_t *dyntexture;
3230                 // check whether its a dynamic texture
3231                 dyntexture = CL_GetDynTexture( basename );
3232                 if (!add && !dyntexture)
3233                         return NULL;
3234                 if (item->merged == item->base)
3235                         item->merged = NULL;
3236                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3237                 R_PurgeTexture(item->stain );item->stain  = NULL;
3238                 R_PurgeTexture(item->merged);item->merged = NULL;
3239                 R_PurgeTexture(item->base  );item->base   = NULL;
3240                 R_PurgeTexture(item->pants );item->pants  = NULL;
3241                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3242                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3243                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3244                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3245                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3246         R_PurgeTexture(item->reflect);item->reflect = NULL;
3247                 item->loadsequence = 0;
3248         }
3249         else if( item->base == NULL )
3250         {
3251                 rtexture_t *dyntexture;
3252                 // check whether its a dynamic texture
3253                 // 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]
3254                 dyntexture = CL_GetDynTexture( basename );
3255                 item->base = dyntexture; // either NULL or dyntexture handle
3256         }
3257
3258         R_SkinFrame_MarkUsed(item);
3259         return item;
3260 }
3261
3262 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3263         { \
3264                 unsigned long long avgcolor[5], wsum; \
3265                 int pix, comp, w; \
3266                 avgcolor[0] = 0; \
3267                 avgcolor[1] = 0; \
3268                 avgcolor[2] = 0; \
3269                 avgcolor[3] = 0; \
3270                 avgcolor[4] = 0; \
3271                 wsum = 0; \
3272                 for(pix = 0; pix < cnt; ++pix) \
3273                 { \
3274                         w = 0; \
3275                         for(comp = 0; comp < 3; ++comp) \
3276                                 w += getpixel; \
3277                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3278                         { \
3279                                 ++wsum; \
3280                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3281                                 w = getpixel; \
3282                                 for(comp = 0; comp < 3; ++comp) \
3283                                         avgcolor[comp] += getpixel * w; \
3284                                 avgcolor[3] += w; \
3285                         } \
3286                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3287                         avgcolor[4] += getpixel; \
3288                 } \
3289                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3290                         avgcolor[3] = 1; \
3291                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3292                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3293                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3294                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3295         }
3296
3297 extern cvar_t gl_picmip;
3298 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3299 {
3300         int j;
3301         unsigned char *pixels;
3302         unsigned char *bumppixels;
3303         unsigned char *basepixels = NULL;
3304         int basepixels_width = 0;
3305         int basepixels_height = 0;
3306         skinframe_t *skinframe;
3307         rtexture_t *ddsbase = NULL;
3308         qboolean ddshasalpha = false;
3309         float ddsavgcolor[4];
3310         char basename[MAX_QPATH];
3311         int miplevel = R_PicmipForFlags(textureflags);
3312         int savemiplevel = miplevel;
3313         int mymiplevel;
3314
3315         if (cls.state == ca_dedicated)
3316                 return NULL;
3317
3318         // return an existing skinframe if already loaded
3319         // if loading of the first image fails, don't make a new skinframe as it
3320         // would cause all future lookups of this to be missing
3321         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3322         if (skinframe && skinframe->base)
3323                 return skinframe;
3324
3325         Image_StripImageExtension(name, basename, sizeof(basename));
3326
3327         // check for DDS texture file first
3328         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3329         {
3330                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3331                 if (basepixels == NULL)
3332                         return NULL;
3333         }
3334
3335         // FIXME handle miplevel
3336
3337         if (developer_loading.integer)
3338                 Con_Printf("loading skin \"%s\"\n", name);
3339
3340         // we've got some pixels to store, so really allocate this new texture now
3341         if (!skinframe)
3342                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3343         textureflags &= ~TEXF_FORCE_RELOAD;
3344         skinframe->stain = NULL;
3345         skinframe->merged = NULL;
3346         skinframe->base = NULL;
3347         skinframe->pants = NULL;
3348         skinframe->shirt = NULL;
3349         skinframe->nmap = NULL;
3350         skinframe->gloss = NULL;
3351         skinframe->glow = NULL;
3352         skinframe->fog = NULL;
3353         skinframe->reflect = NULL;
3354         skinframe->hasalpha = false;
3355
3356         if (ddsbase)
3357         {
3358                 skinframe->base = ddsbase;
3359                 skinframe->hasalpha = ddshasalpha;
3360                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3361                 if (r_loadfog && skinframe->hasalpha)
3362                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3363                 //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]);
3364         }
3365         else
3366         {
3367                 basepixels_width = image_width;
3368                 basepixels_height = image_height;
3369                 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);
3370                 if (textureflags & TEXF_ALPHA)
3371                 {
3372                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3373                         {
3374                                 if (basepixels[j] < 255)
3375                                 {
3376                                         skinframe->hasalpha = true;
3377                                         break;
3378                                 }
3379                         }
3380                         if (r_loadfog && skinframe->hasalpha)
3381                         {
3382                                 // has transparent pixels
3383                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3384                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3385                                 {
3386                                         pixels[j+0] = 255;
3387                                         pixels[j+1] = 255;
3388                                         pixels[j+2] = 255;
3389                                         pixels[j+3] = basepixels[j+3];
3390                                 }
3391                                 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);
3392                                 Mem_Free(pixels);
3393                         }
3394                 }
3395                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3396 #ifndef USE_GLES2
3397                 //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]);
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3399                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3400                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3401                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3402 #endif
3403         }
3404
3405         if (r_loaddds)
3406         {
3407                 mymiplevel = savemiplevel;
3408                 if (r_loadnormalmap)
3409                         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);
3410                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3411                 if (r_loadgloss)
3412                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3413                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3414                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3415                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3416         }
3417
3418         // _norm is the name used by tenebrae and has been adopted as standard
3419         if (r_loadnormalmap && skinframe->nmap == NULL)
3420         {
3421                 mymiplevel = savemiplevel;
3422                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3423                 {
3424                         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);
3425                         Mem_Free(pixels);
3426                         pixels = NULL;
3427                 }
3428                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3429                 {
3430                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3431                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3432                         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);
3433                         Mem_Free(pixels);
3434                         Mem_Free(bumppixels);
3435                 }
3436                 else if (r_shadow_bumpscale_basetexture.value > 0)
3437                 {
3438                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3439                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3440                         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);
3441                         Mem_Free(pixels);
3442                 }
3443 #ifndef USE_GLES2
3444                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3445                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3446 #endif
3447         }
3448
3449         // _luma is supported only for tenebrae compatibility
3450         // _glow is the preferred name
3451         mymiplevel = savemiplevel;
3452         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))))
3453         {
3454                 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);
3455 #ifndef USE_GLES2
3456                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3457                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3458 #endif
3459                 Mem_Free(pixels);pixels = NULL;
3460         }
3461
3462         mymiplevel = savemiplevel;
3463         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3464         {
3465                 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);
3466 #ifndef USE_GLES2
3467                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3468                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3469 #endif
3470                 Mem_Free(pixels);
3471                 pixels = NULL;
3472         }
3473
3474         mymiplevel = savemiplevel;
3475         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3476         {
3477                 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);
3478 #ifndef USE_GLES2
3479                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3480                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3481 #endif
3482                 Mem_Free(pixels);
3483                 pixels = NULL;
3484         }
3485
3486         mymiplevel = savemiplevel;
3487         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3488         {
3489                 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);
3490 #ifndef USE_GLES2
3491                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3492                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3493 #endif
3494                 Mem_Free(pixels);
3495                 pixels = NULL;
3496         }
3497
3498         mymiplevel = savemiplevel;
3499         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3500         {
3501                 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);
3502 #ifndef USE_GLES2
3503                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3504                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3505 #endif
3506                 Mem_Free(pixels);
3507                 pixels = NULL;
3508         }
3509
3510         if (basepixels)
3511                 Mem_Free(basepixels);
3512
3513         return skinframe;
3514 }
3515
3516 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3517 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3518 {
3519         int i;
3520         unsigned char *temp1, *temp2;
3521         skinframe_t *skinframe;
3522
3523         if (cls.state == ca_dedicated)
3524                 return NULL;
3525
3526         // if already loaded just return it, otherwise make a new skinframe
3527         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3528         if (skinframe && skinframe->base)
3529                 return skinframe;
3530         textureflags &= ~TEXF_FORCE_RELOAD;
3531
3532         skinframe->stain = NULL;
3533         skinframe->merged = NULL;
3534         skinframe->base = NULL;
3535         skinframe->pants = NULL;
3536         skinframe->shirt = NULL;
3537         skinframe->nmap = NULL;
3538         skinframe->gloss = NULL;
3539         skinframe->glow = NULL;
3540         skinframe->fog = NULL;
3541         skinframe->reflect = NULL;
3542         skinframe->hasalpha = false;
3543
3544         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3545         if (!skindata)
3546                 return NULL;
3547
3548         if (developer_loading.integer)
3549                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3550
3551         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3552         {
3553                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3554                 temp2 = temp1 + width * height * 4;
3555                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3556                 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);
3557                 Mem_Free(temp1);
3558         }
3559         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3560         if (textureflags & TEXF_ALPHA)
3561         {
3562                 for (i = 3;i < width * height * 4;i += 4)
3563                 {
3564                         if (skindata[i] < 255)
3565                         {
3566                                 skinframe->hasalpha = true;
3567                                 break;
3568                         }
3569                 }
3570                 if (r_loadfog && skinframe->hasalpha)
3571                 {
3572                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3573                         memcpy(fogpixels, skindata, width * height * 4);
3574                         for (i = 0;i < width * height * 4;i += 4)
3575                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3576                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3577                         Mem_Free(fogpixels);
3578                 }
3579         }
3580
3581         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3582         //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]);
3583
3584         return skinframe;
3585 }
3586
3587 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3588 {
3589         int i;
3590         int featuresmask;
3591         skinframe_t *skinframe;
3592
3593         if (cls.state == ca_dedicated)
3594                 return NULL;
3595
3596         // if already loaded just return it, otherwise make a new skinframe
3597         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3598         if (skinframe && skinframe->base)
3599                 return skinframe;
3600         textureflags &= ~TEXF_FORCE_RELOAD;
3601
3602         skinframe->stain = NULL;
3603         skinframe->merged = NULL;
3604         skinframe->base = NULL;
3605         skinframe->pants = NULL;
3606         skinframe->shirt = NULL;
3607         skinframe->nmap = NULL;
3608         skinframe->gloss = NULL;
3609         skinframe->glow = NULL;
3610         skinframe->fog = NULL;
3611         skinframe->reflect = NULL;
3612         skinframe->hasalpha = false;
3613
3614         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3615         if (!skindata)
3616                 return NULL;
3617
3618         if (developer_loading.integer)
3619                 Con_Printf("loading quake skin \"%s\"\n", name);
3620
3621         // 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)
3622         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3623         memcpy(skinframe->qpixels, skindata, width*height);
3624         skinframe->qwidth = width;
3625         skinframe->qheight = height;
3626
3627         featuresmask = 0;
3628         for (i = 0;i < width * height;i++)
3629                 featuresmask |= palette_featureflags[skindata[i]];
3630
3631         skinframe->hasalpha = false;
3632         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3633         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3634         skinframe->qgeneratemerged = true;
3635         skinframe->qgeneratebase = skinframe->qhascolormapping;
3636         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3637
3638         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3639         //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]);
3640
3641         return skinframe;
3642 }
3643
3644 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3645 {
3646         int width;
3647         int height;
3648         unsigned char *skindata;
3649
3650         if (!skinframe->qpixels)
3651                 return;
3652
3653         if (!skinframe->qhascolormapping)
3654                 colormapped = false;
3655
3656         if (colormapped)
3657         {
3658                 if (!skinframe->qgeneratebase)
3659                         return;
3660         }
3661         else
3662         {
3663                 if (!skinframe->qgeneratemerged)
3664                         return;
3665         }
3666
3667         width = skinframe->qwidth;
3668         height = skinframe->qheight;
3669         skindata = skinframe->qpixels;
3670
3671         if (skinframe->qgeneratenmap)
3672         {
3673                 unsigned char *temp1, *temp2;
3674                 skinframe->qgeneratenmap = false;
3675                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3676                 temp2 = temp1 + width * height * 4;
3677                 // use either a custom palette or the quake palette
3678                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3679                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3680                 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);
3681                 Mem_Free(temp1);
3682         }
3683
3684         if (skinframe->qgenerateglow)
3685         {
3686                 skinframe->qgenerateglow = false;
3687                 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
3688         }
3689
3690         if (colormapped)
3691         {
3692                 skinframe->qgeneratebase = false;
3693                 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);
3694                 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);
3695                 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);
3696         }
3697         else
3698         {
3699                 skinframe->qgeneratemerged = false;
3700                 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);
3701         }
3702
3703         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3704         {
3705                 Mem_Free(skinframe->qpixels);
3706                 skinframe->qpixels = NULL;
3707         }
3708 }
3709
3710 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)
3711 {
3712         int i;
3713         skinframe_t *skinframe;
3714
3715         if (cls.state == ca_dedicated)
3716                 return NULL;
3717
3718         // if already loaded just return it, otherwise make a new skinframe
3719         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3720         if (skinframe && skinframe->base)
3721                 return skinframe;
3722         textureflags &= ~TEXF_FORCE_RELOAD;
3723
3724         skinframe->stain = NULL;
3725         skinframe->merged = NULL;
3726         skinframe->base = NULL;
3727         skinframe->pants = NULL;
3728         skinframe->shirt = NULL;
3729         skinframe->nmap = NULL;
3730         skinframe->gloss = NULL;
3731         skinframe->glow = NULL;
3732         skinframe->fog = NULL;
3733         skinframe->reflect = NULL;
3734         skinframe->hasalpha = false;
3735
3736         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3737         if (!skindata)
3738                 return NULL;
3739
3740         if (developer_loading.integer)
3741                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3742
3743         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3744         if (textureflags & TEXF_ALPHA)
3745         {
3746                 for (i = 0;i < width * height;i++)
3747                 {
3748                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3749                         {
3750                                 skinframe->hasalpha = true;
3751                                 break;
3752                         }
3753                 }
3754                 if (r_loadfog && skinframe->hasalpha)
3755                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3756         }
3757
3758         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3759         //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]);
3760
3761         return skinframe;
3762 }
3763
3764 skinframe_t *R_SkinFrame_LoadMissing(void)
3765 {
3766         skinframe_t *skinframe;
3767
3768         if (cls.state == ca_dedicated)
3769                 return NULL;
3770
3771         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3772         skinframe->stain = NULL;
3773         skinframe->merged = NULL;
3774         skinframe->base = NULL;
3775         skinframe->pants = NULL;
3776         skinframe->shirt = NULL;
3777         skinframe->nmap = NULL;
3778         skinframe->gloss = NULL;
3779         skinframe->glow = NULL;
3780         skinframe->fog = NULL;
3781         skinframe->reflect = NULL;
3782         skinframe->hasalpha = false;
3783
3784         skinframe->avgcolor[0] = rand() / RAND_MAX;
3785         skinframe->avgcolor[1] = rand() / RAND_MAX;
3786         skinframe->avgcolor[2] = rand() / RAND_MAX;
3787         skinframe->avgcolor[3] = 1;
3788
3789         return skinframe;
3790 }
3791
3792 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3793 typedef struct suffixinfo_s
3794 {
3795         const char *suffix;
3796         qboolean flipx, flipy, flipdiagonal;
3797 }
3798 suffixinfo_t;
3799 static suffixinfo_t suffix[3][6] =
3800 {
3801         {
3802                 {"px",   false, false, false},
3803                 {"nx",   false, false, false},
3804                 {"py",   false, false, false},
3805                 {"ny",   false, false, false},
3806                 {"pz",   false, false, false},
3807                 {"nz",   false, false, false}
3808         },
3809         {
3810                 {"posx", false, false, false},
3811                 {"negx", false, false, false},
3812                 {"posy", false, false, false},
3813                 {"negy", false, false, false},
3814                 {"posz", false, false, false},
3815                 {"negz", false, false, false}
3816         },
3817         {
3818                 {"rt",    true, false,  true},
3819                 {"lf",   false,  true,  true},
3820                 {"ft",    true,  true, false},
3821                 {"bk",   false, false, false},
3822                 {"up",    true, false,  true},
3823                 {"dn",    true, false,  true}
3824         }
3825 };
3826
3827 static int componentorder[4] = {0, 1, 2, 3};
3828
3829 rtexture_t *R_LoadCubemap(const char *basename)
3830 {
3831         int i, j, cubemapsize;
3832         unsigned char *cubemappixels, *image_buffer;
3833         rtexture_t *cubemaptexture;
3834         char name[256];
3835         // must start 0 so the first loadimagepixels has no requested width/height
3836         cubemapsize = 0;
3837         cubemappixels = NULL;
3838         cubemaptexture = NULL;
3839         // keep trying different suffix groups (posx, px, rt) until one loads
3840         for (j = 0;j < 3 && !cubemappixels;j++)
3841         {
3842                 // load the 6 images in the suffix group
3843                 for (i = 0;i < 6;i++)
3844                 {
3845                         // generate an image name based on the base and and suffix
3846                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3847                         // load it
3848                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3849                         {
3850                                 // an image loaded, make sure width and height are equal
3851                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3852                                 {
3853                                         // if this is the first image to load successfully, allocate the cubemap memory
3854                                         if (!cubemappixels && image_width >= 1)
3855                                         {
3856                                                 cubemapsize = image_width;
3857                                                 // note this clears to black, so unavailable sides are black
3858                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3859                                         }
3860                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3861                                         if (cubemappixels)
3862                                                 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);
3863                                 }
3864                                 else
3865                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3866                                 // free the image
3867                                 Mem_Free(image_buffer);
3868                         }
3869                 }
3870         }
3871         // if a cubemap loaded, upload it
3872         if (cubemappixels)
3873         {
3874                 if (developer_loading.integer)
3875                         Con_Printf("loading cubemap \"%s\"\n", basename);
3876
3877                 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);
3878                 Mem_Free(cubemappixels);
3879         }
3880         else
3881         {
3882                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3883                 if (developer_loading.integer)
3884                 {
3885                         Con_Printf("(tried tried images ");
3886                         for (j = 0;j < 3;j++)
3887                                 for (i = 0;i < 6;i++)
3888                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3889                         Con_Print(" and was unable to find any of them).\n");
3890                 }
3891         }
3892         return cubemaptexture;
3893 }
3894
3895 rtexture_t *R_GetCubemap(const char *basename)
3896 {
3897         int i;
3898         for (i = 0;i < r_texture_numcubemaps;i++)
3899                 if (r_texture_cubemaps[i] != NULL)
3900                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3901                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3902         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3903                 return r_texture_whitecube;
3904         r_texture_numcubemaps++;
3905         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3906         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3907         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3908         return r_texture_cubemaps[i]->texture;
3909 }
3910
3911 void R_FreeCubemap(const char *basename)
3912 {
3913         int i;
3914
3915         for (i = 0;i < r_texture_numcubemaps;i++)
3916         {
3917                 if (r_texture_cubemaps[i] != NULL)
3918                 {
3919                         if (r_texture_cubemaps[i]->texture)
3920                         {
3921                                 if (developer_loading.integer)
3922                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3923                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3924                                 Mem_Free(r_texture_cubemaps[i]);
3925                                 r_texture_cubemaps[i] = NULL;
3926                         }
3927                 }
3928         }
3929 }
3930
3931 void R_FreeCubemaps(void)
3932 {
3933         int i;
3934         for (i = 0;i < r_texture_numcubemaps;i++)
3935         {
3936                 if (developer_loading.integer)
3937                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3938                 if (r_texture_cubemaps[i] != NULL)
3939                 {
3940                         if (r_texture_cubemaps[i]->texture)
3941                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3942                         Mem_Free(r_texture_cubemaps[i]);
3943                 }
3944         }
3945         r_texture_numcubemaps = 0;
3946 }
3947
3948 void R_Main_FreeViewCache(void)
3949 {
3950         if (r_refdef.viewcache.entityvisible)
3951                 Mem_Free(r_refdef.viewcache.entityvisible);
3952         if (r_refdef.viewcache.world_pvsbits)
3953                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3954         if (r_refdef.viewcache.world_leafvisible)
3955                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3956         if (r_refdef.viewcache.world_surfacevisible)
3957                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3958         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3959 }
3960
3961 void R_Main_ResizeViewCache(void)
3962 {
3963         int numentities = r_refdef.scene.numentities;
3964         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3965         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3966         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3967         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3968         if (r_refdef.viewcache.maxentities < numentities)
3969         {
3970                 r_refdef.viewcache.maxentities = numentities;
3971                 if (r_refdef.viewcache.entityvisible)
3972                         Mem_Free(r_refdef.viewcache.entityvisible);
3973                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3974         }
3975         if (r_refdef.viewcache.world_numclusters != numclusters)
3976         {
3977                 r_refdef.viewcache.world_numclusters = numclusters;
3978                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3979                 if (r_refdef.viewcache.world_pvsbits)
3980                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3981                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3982         }
3983         if (r_refdef.viewcache.world_numleafs != numleafs)
3984         {
3985                 r_refdef.viewcache.world_numleafs = numleafs;
3986                 if (r_refdef.viewcache.world_leafvisible)
3987                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3988                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3989         }
3990         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3991         {
3992                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3993                 if (r_refdef.viewcache.world_surfacevisible)
3994                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3995                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3996         }
3997 }
3998
3999 extern rtexture_t *loadingscreentexture;
4000 void gl_main_start(void)
4001 {
4002         loadingscreentexture = NULL;
4003         r_texture_blanknormalmap = NULL;
4004         r_texture_white = NULL;
4005         r_texture_grey128 = NULL;
4006         r_texture_black = NULL;
4007         r_texture_whitecube = NULL;
4008         r_texture_normalizationcube = NULL;
4009         r_texture_fogattenuation = NULL;
4010         r_texture_fogheighttexture = NULL;
4011         r_texture_gammaramps = NULL;
4012         r_texture_numcubemaps = 0;
4013
4014         r_loaddds = r_texture_dds_load.integer != 0;
4015         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4016
4017         switch(vid.renderpath)
4018         {
4019         case RENDERPATH_GL20:
4020         case RENDERPATH_D3D9:
4021         case RENDERPATH_D3D10:
4022         case RENDERPATH_D3D11:
4023         case RENDERPATH_SOFT:
4024         case RENDERPATH_GLES2:
4025                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4026                 Cvar_SetValueQuick(&gl_combine, 1);
4027                 Cvar_SetValueQuick(&r_glsl, 1);
4028                 r_loadnormalmap = true;
4029                 r_loadgloss = true;
4030                 r_loadfog = false;
4031                 break;
4032         case RENDERPATH_GL13:
4033         case RENDERPATH_GLES1:
4034                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4035                 Cvar_SetValueQuick(&gl_combine, 1);
4036                 Cvar_SetValueQuick(&r_glsl, 0);
4037                 r_loadnormalmap = false;
4038                 r_loadgloss = false;
4039                 r_loadfog = true;
4040                 break;
4041         case RENDERPATH_GL11:
4042                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4043                 Cvar_SetValueQuick(&gl_combine, 0);
4044                 Cvar_SetValueQuick(&r_glsl, 0);
4045                 r_loadnormalmap = false;
4046                 r_loadgloss = false;
4047                 r_loadfog = true;
4048                 break;
4049         }
4050
4051         R_AnimCache_Free();
4052         R_FrameData_Reset();
4053
4054         r_numqueries = 0;
4055         r_maxqueries = 0;
4056         memset(r_queries, 0, sizeof(r_queries));
4057
4058         r_qwskincache = NULL;
4059         r_qwskincache_size = 0;
4060
4061         // due to caching of texture_t references, the collision cache must be reset
4062         Collision_Cache_Reset(true);
4063
4064         // set up r_skinframe loading system for textures
4065         memset(&r_skinframe, 0, sizeof(r_skinframe));
4066         r_skinframe.loadsequence = 1;
4067         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4068
4069         r_main_texturepool = R_AllocTexturePool();
4070         R_BuildBlankTextures();
4071         R_BuildNoTexture();
4072         if (vid.support.arb_texture_cube_map)
4073         {
4074                 R_BuildWhiteCube();
4075                 R_BuildNormalizationCube();
4076         }
4077         r_texture_fogattenuation = NULL;
4078         r_texture_fogheighttexture = NULL;
4079         r_texture_gammaramps = NULL;
4080         //r_texture_fogintensity = NULL;
4081         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4082         memset(&r_waterstate, 0, sizeof(r_waterstate));
4083         r_glsl_permutation = NULL;
4084         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4086         glslshaderstring = NULL;
4087 #ifdef SUPPORTD3D
4088         r_hlsl_permutation = NULL;
4089         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4091 #endif
4092         hlslshaderstring = NULL;
4093         memset(&r_svbsp, 0, sizeof (r_svbsp));
4094
4095         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4096         r_texture_numcubemaps = 0;
4097
4098         r_refdef.fogmasktable_density = 0;
4099 }
4100
4101 void gl_main_shutdown(void)
4102 {
4103         R_AnimCache_Free();
4104         R_FrameData_Reset();
4105
4106         R_Main_FreeViewCache();
4107
4108         switch(vid.renderpath)
4109         {
4110         case RENDERPATH_GL11:
4111         case RENDERPATH_GL13:
4112         case RENDERPATH_GL20:
4113         case RENDERPATH_GLES1:
4114         case RENDERPATH_GLES2:
4115 #ifdef GL_SAMPLES_PASSED_ARB
4116                 if (r_maxqueries)
4117                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4118 #endif
4119                 break;
4120         case RENDERPATH_D3D9:
4121                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4122                 break;
4123         case RENDERPATH_D3D10:
4124                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4125                 break;
4126         case RENDERPATH_D3D11:
4127                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4128                 break;
4129         case RENDERPATH_SOFT:
4130                 break;
4131         }
4132
4133         r_numqueries = 0;
4134         r_maxqueries = 0;
4135         memset(r_queries, 0, sizeof(r_queries));
4136
4137         r_qwskincache = NULL;
4138         r_qwskincache_size = 0;
4139
4140         // clear out the r_skinframe state
4141         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4142         memset(&r_skinframe, 0, sizeof(r_skinframe));
4143
4144         if (r_svbsp.nodes)
4145                 Mem_Free(r_svbsp.nodes);
4146         memset(&r_svbsp, 0, sizeof (r_svbsp));
4147         R_FreeTexturePool(&r_main_texturepool);
4148         loadingscreentexture = NULL;
4149         r_texture_blanknormalmap = NULL;
4150         r_texture_white = NULL;
4151         r_texture_grey128 = NULL;
4152         r_texture_black = NULL;
4153         r_texture_whitecube = NULL;
4154         r_texture_normalizationcube = NULL;
4155         r_texture_fogattenuation = NULL;
4156         r_texture_fogheighttexture = NULL;
4157         r_texture_gammaramps = NULL;
4158         r_texture_numcubemaps = 0;
4159         //r_texture_fogintensity = NULL;
4160         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4161         memset(&r_waterstate, 0, sizeof(r_waterstate));
4162         R_GLSL_Restart_f();
4163
4164         r_glsl_permutation = NULL;
4165         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4166         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4167         glslshaderstring = NULL;
4168 #ifdef SUPPORTD3D
4169         r_hlsl_permutation = NULL;
4170         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4171         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4172 #endif
4173         hlslshaderstring = NULL;
4174 }
4175
4176 extern void CL_ParseEntityLump(char *entitystring);
4177 void gl_main_newmap(void)
4178 {
4179         // FIXME: move this code to client
4180         char *entities, entname[MAX_QPATH];
4181         if (r_qwskincache)
4182                 Mem_Free(r_qwskincache);
4183         r_qwskincache = NULL;
4184         r_qwskincache_size = 0;
4185         if (cl.worldmodel)
4186         {
4187                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4188                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4189                 {
4190                         CL_ParseEntityLump(entities);
4191                         Mem_Free(entities);
4192                         return;
4193                 }
4194                 if (cl.worldmodel->brush.entities)
4195                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4196         }
4197         R_Main_FreeViewCache();
4198
4199         R_FrameData_Reset();
4200 }
4201
4202 void GL_Main_Init(void)
4203 {
4204         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4205
4206         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4207         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4208         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4209         if (gamemode == GAME_NEHAHRA)
4210         {
4211                 Cvar_RegisterVariable (&gl_fogenable);
4212                 Cvar_RegisterVariable (&gl_fogdensity);
4213                 Cvar_RegisterVariable (&gl_fogred);
4214                 Cvar_RegisterVariable (&gl_foggreen);
4215                 Cvar_RegisterVariable (&gl_fogblue);
4216                 Cvar_RegisterVariable (&gl_fogstart);
4217                 Cvar_RegisterVariable (&gl_fogend);
4218                 Cvar_RegisterVariable (&gl_skyclip);
4219         }
4220         Cvar_RegisterVariable(&r_motionblur);
4221         Cvar_RegisterVariable(&r_damageblur);
4222         Cvar_RegisterVariable(&r_motionblur_averaging);
4223         Cvar_RegisterVariable(&r_motionblur_randomize);
4224         Cvar_RegisterVariable(&r_motionblur_minblur);
4225         Cvar_RegisterVariable(&r_motionblur_maxblur);
4226         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4227         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4228         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4229         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4230         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4231         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4232         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4233         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4234         Cvar_RegisterVariable(&r_equalize_entities_by);
4235         Cvar_RegisterVariable(&r_equalize_entities_to);
4236         Cvar_RegisterVariable(&r_depthfirst);
4237         Cvar_RegisterVariable(&r_useinfinitefarclip);
4238         Cvar_RegisterVariable(&r_farclip_base);
4239         Cvar_RegisterVariable(&r_farclip_world);
4240         Cvar_RegisterVariable(&r_nearclip);
4241         Cvar_RegisterVariable(&r_deformvertexes);
4242         Cvar_RegisterVariable(&r_transparent);
4243         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4244         Cvar_RegisterVariable(&r_showoverdraw);
4245         Cvar_RegisterVariable(&r_showbboxes);
4246         Cvar_RegisterVariable(&r_showsurfaces);
4247         Cvar_RegisterVariable(&r_showtris);
4248         Cvar_RegisterVariable(&r_shownormals);
4249         Cvar_RegisterVariable(&r_showlighting);
4250         Cvar_RegisterVariable(&r_showshadowvolumes);
4251         Cvar_RegisterVariable(&r_showcollisionbrushes);
4252         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4253         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4254         Cvar_RegisterVariable(&r_showdisabledepthtest);
4255         Cvar_RegisterVariable(&r_drawportals);
4256         Cvar_RegisterVariable(&r_drawentities);
4257         Cvar_RegisterVariable(&r_draw2d);
4258         Cvar_RegisterVariable(&r_drawworld);
4259         Cvar_RegisterVariable(&r_cullentities_trace);
4260         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4261         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4262         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4263         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4264         Cvar_RegisterVariable(&r_sortentities);
4265         Cvar_RegisterVariable(&r_drawviewmodel);
4266         Cvar_RegisterVariable(&r_drawexteriormodel);
4267         Cvar_RegisterVariable(&r_speeds);
4268         Cvar_RegisterVariable(&r_fullbrights);
4269         Cvar_RegisterVariable(&r_wateralpha);
4270         Cvar_RegisterVariable(&r_dynamic);
4271         Cvar_RegisterVariable(&r_fakelight);
4272         Cvar_RegisterVariable(&r_fakelight_intensity);
4273         Cvar_RegisterVariable(&r_fullbright);
4274         Cvar_RegisterVariable(&r_shadows);
4275         Cvar_RegisterVariable(&r_shadows_darken);
4276         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4277         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4278         Cvar_RegisterVariable(&r_shadows_throwdistance);
4279         Cvar_RegisterVariable(&r_shadows_throwdirection);
4280         Cvar_RegisterVariable(&r_shadows_focus);
4281         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4282         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4283         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4284         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4285         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4286         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4287         Cvar_RegisterVariable(&r_fog_exp2);
4288         Cvar_RegisterVariable(&r_fog_clear);
4289         Cvar_RegisterVariable(&r_drawfog);
4290         Cvar_RegisterVariable(&r_transparentdepthmasking);
4291         Cvar_RegisterVariable(&r_transparent_sortmindist);
4292         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4293         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4294         Cvar_RegisterVariable(&r_texture_dds_load);
4295         Cvar_RegisterVariable(&r_texture_dds_save);
4296         Cvar_RegisterVariable(&r_textureunits);
4297         Cvar_RegisterVariable(&gl_combine);
4298         Cvar_RegisterVariable(&r_viewfbo);
4299         Cvar_RegisterVariable(&r_viewscale);
4300         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4301         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4302         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4303         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4304         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4305         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4306         Cvar_RegisterVariable(&r_glsl);
4307         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4308         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4309         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4310         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4311         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4312         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4313         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4314         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4315         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4316         Cvar_RegisterVariable(&r_glsl_postprocess);
4317         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4318         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4319         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4320         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4321         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4322         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4323         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4324         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4325
4326         Cvar_RegisterVariable(&r_water);
4327         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4328         Cvar_RegisterVariable(&r_water_clippingplanebias);
4329         Cvar_RegisterVariable(&r_water_refractdistort);
4330         Cvar_RegisterVariable(&r_water_reflectdistort);
4331         Cvar_RegisterVariable(&r_water_scissormode);
4332         Cvar_RegisterVariable(&r_water_lowquality);
4333         Cvar_RegisterVariable(&r_water_hideplayer);
4334
4335         Cvar_RegisterVariable(&r_lerpsprites);
4336         Cvar_RegisterVariable(&r_lerpmodels);
4337         Cvar_RegisterVariable(&r_lerplightstyles);
4338         Cvar_RegisterVariable(&r_waterscroll);
4339         Cvar_RegisterVariable(&r_bloom);
4340         Cvar_RegisterVariable(&r_bloom_colorscale);
4341         Cvar_RegisterVariable(&r_bloom_brighten);
4342         Cvar_RegisterVariable(&r_bloom_blur);
4343         Cvar_RegisterVariable(&r_bloom_resolution);
4344         Cvar_RegisterVariable(&r_bloom_colorexponent);
4345         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4346         Cvar_RegisterVariable(&r_hdr);
4347         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4348         Cvar_RegisterVariable(&r_hdr_glowintensity);
4349         Cvar_RegisterVariable(&r_hdr_range);
4350         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4351         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4352         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4353         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4354         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4355         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4356         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4357         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4358         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4359         Cvar_RegisterVariable(&developer_texturelogging);
4360         Cvar_RegisterVariable(&gl_lightmaps);
4361         Cvar_RegisterVariable(&r_test);
4362         Cvar_RegisterVariable(&r_glsl_saturation);
4363         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4364         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4365         Cvar_RegisterVariable(&r_framedatasize);
4366         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4367                 Cvar_SetValue("r_fullbrights", 0);
4368         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4369 }
4370
4371 extern void R_Textures_Init(void);
4372 extern void GL_Draw_Init(void);
4373 extern void GL_Main_Init(void);
4374 extern void R_Shadow_Init(void);
4375 extern void R_Sky_Init(void);
4376 extern void GL_Surf_Init(void);
4377 extern void R_Particles_Init(void);
4378 extern void R_Explosion_Init(void);
4379 extern void gl_backend_init(void);
4380 extern void Sbar_Init(void);
4381 extern void R_LightningBeams_Init(void);
4382 extern void Mod_RenderInit(void);
4383 extern void Font_Init(void);
4384
4385 void Render_Init(void)
4386 {
4387         gl_backend_init();
4388         R_Textures_Init();
4389         GL_Main_Init();
4390         Font_Init();
4391         GL_Draw_Init();
4392         R_Shadow_Init();
4393         R_Sky_Init();
4394         GL_Surf_Init();
4395         Sbar_Init();
4396         R_Particles_Init();
4397         R_Explosion_Init();
4398         R_LightningBeams_Init();
4399         Mod_RenderInit();
4400 }
4401
4402 /*
4403 ===============
4404 GL_Init
4405 ===============
4406 */
4407 #ifndef USE_GLES2
4408 extern char *ENGINE_EXTENSIONS;
4409 void GL_Init (void)
4410 {
4411         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4412         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4413         gl_version = (const char *)qglGetString(GL_VERSION);
4414         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4415
4416         if (!gl_extensions)
4417                 gl_extensions = "";
4418         if (!gl_platformextensions)
4419                 gl_platformextensions = "";
4420
4421         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4422         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4423         Con_Printf("GL_VERSION: %s\n", gl_version);
4424         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4425         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4426
4427         VID_CheckExtensions();
4428
4429         // LordHavoc: report supported extensions
4430         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4431
4432         // clear to black (loading plaque will be seen over this)
4433         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4434 }
4435 #endif
4436
4437 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4438 {
4439         int i;
4440         mplane_t *p;
4441         if (r_trippy.integer)
4442                 return false;
4443         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4444         {
4445                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4446                 if (i == 4)
4447                         continue;
4448                 p = r_refdef.view.frustum + i;
4449                 switch(p->signbits)
4450                 {
4451                 default:
4452                 case 0:
4453                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 1:
4457                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 2:
4461                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 3:
4465                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 4:
4469                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 5:
4473                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 6:
4477                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 7:
4481                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 }
4485         }
4486         return false;
4487 }
4488
4489 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4490 {
4491         int i;
4492         const mplane_t *p;
4493         if (r_trippy.integer)
4494                 return false;
4495         for (i = 0;i < numplanes;i++)
4496         {
4497                 p = planes + i;
4498                 switch(p->signbits)
4499                 {
4500                 default:
4501                 case 0:
4502                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4503                                 return true;
4504                         break;
4505                 case 1:
4506                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4507                                 return true;
4508                         break;
4509                 case 2:
4510                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4511                                 return true;
4512                         break;
4513                 case 3:
4514                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4515                                 return true;
4516                         break;
4517                 case 4:
4518                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4519                                 return true;
4520                         break;
4521                 case 5:
4522                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4523                                 return true;
4524                         break;
4525                 case 6:
4526                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4527                                 return true;
4528                         break;
4529                 case 7:
4530                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4531                                 return true;
4532                         break;
4533                 }
4534         }
4535         return false;
4536 }
4537
4538 //==================================================================================
4539
4540 // LordHavoc: this stores temporary data used within the same frame
4541
4542 typedef struct r_framedata_mem_s
4543 {
4544         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4545         size_t size; // how much usable space
4546         size_t current; // how much space in use
4547         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4548         size_t wantedsize; // how much space was allocated
4549         unsigned char *data; // start of real data (16byte aligned)
4550 }
4551 r_framedata_mem_t;
4552
4553 static r_framedata_mem_t *r_framedata_mem;
4554
4555 void R_FrameData_Reset(void)
4556 {
4557         while (r_framedata_mem)
4558         {
4559                 r_framedata_mem_t *next = r_framedata_mem->purge;
4560                 Mem_Free(r_framedata_mem);
4561                 r_framedata_mem = next;
4562         }
4563 }
4564
4565 void R_FrameData_Resize(void)
4566 {
4567         size_t wantedsize;
4568         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4569         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4570         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4571         {
4572                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4573                 newmem->wantedsize = wantedsize;
4574                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4575                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4576                 newmem->current = 0;
4577                 newmem->mark = 0;
4578                 newmem->purge = r_framedata_mem;
4579                 r_framedata_mem = newmem;
4580         }
4581 }
4582
4583 void R_FrameData_NewFrame(void)
4584 {
4585         R_FrameData_Resize();
4586         if (!r_framedata_mem)
4587                 return;
4588         // if we ran out of space on the last frame, free the old memory now
4589         while (r_framedata_mem->purge)
4590         {
4591                 // repeatedly remove the second item in the list, leaving only head
4592                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4593                 Mem_Free(r_framedata_mem->purge);
4594                 r_framedata_mem->purge = next;
4595         }
4596         // reset the current mem pointer
4597         r_framedata_mem->current = 0;
4598         r_framedata_mem->mark = 0;
4599 }
4600
4601 void *R_FrameData_Alloc(size_t size)
4602 {
4603         void *data;
4604
4605         // align to 16 byte boundary - the data pointer is already aligned, so we
4606         // only need to ensure the size of every allocation is also aligned
4607         size = (size + 15) & ~15;
4608
4609         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4610         {
4611                 // emergency - we ran out of space, allocate more memory
4612                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4613                 R_FrameData_Resize();
4614         }
4615
4616         data = r_framedata_mem->data + r_framedata_mem->current;
4617         r_framedata_mem->current += size;
4618
4619         // count the usage for stats
4620         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4621         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4622
4623         return (void *)data;
4624 }
4625
4626 void *R_FrameData_Store(size_t size, void *data)
4627 {
4628         void *d = R_FrameData_Alloc(size);
4629         if (d && data)
4630                 memcpy(d, data, size);
4631         return d;
4632 }
4633
4634 void R_FrameData_SetMark(void)
4635 {
4636         if (!r_framedata_mem)
4637                 return;
4638         r_framedata_mem->mark = r_framedata_mem->current;
4639 }
4640
4641 void R_FrameData_ReturnToMark(void)
4642 {
4643         if (!r_framedata_mem)
4644                 return;
4645         r_framedata_mem->current = r_framedata_mem->mark;
4646 }
4647
4648 //==================================================================================
4649
4650 // LordHavoc: animcache originally written by Echon, rewritten since then
4651
4652 /**
4653  * Animation cache prevents re-generating mesh data for an animated model
4654  * multiple times in one frame for lighting, shadowing, reflections, etc.
4655  */
4656
4657 void R_AnimCache_Free(void)
4658 {
4659 }
4660
4661 void R_AnimCache_ClearCache(void)
4662 {
4663         int i;
4664         entity_render_t *ent;
4665
4666         for (i = 0;i < r_refdef.scene.numentities;i++)
4667         {
4668                 ent = r_refdef.scene.entities[i];
4669                 ent->animcache_vertex3f = NULL;
4670                 ent->animcache_normal3f = NULL;
4671                 ent->animcache_svector3f = NULL;
4672                 ent->animcache_tvector3f = NULL;
4673                 ent->animcache_vertexmesh = NULL;
4674                 ent->animcache_vertex3fbuffer = NULL;
4675                 ent->animcache_vertexmeshbuffer = NULL;
4676         }
4677 }
4678
4679 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4680 {
4681         int i;
4682
4683         // check if we need the meshbuffers
4684         if (!vid.useinterleavedarrays)
4685                 return;
4686
4687         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4688                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4689         // TODO: upload vertex3f buffer?
4690         if (ent->animcache_vertexmesh)
4691         {
4692                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4693                 for (i = 0;i < numvertices;i++)
4694                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4695                 if (ent->animcache_svector3f)
4696                         for (i = 0;i < numvertices;i++)
4697                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4698                 if (ent->animcache_tvector3f)
4699                         for (i = 0;i < numvertices;i++)
4700                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4701                 if (ent->animcache_normal3f)
4702                         for (i = 0;i < numvertices;i++)
4703                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4704                 // TODO: upload vertexmeshbuffer?
4705         }
4706 }
4707
4708 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4709 {
4710         dp_model_t *model = ent->model;
4711         int numvertices;
4712         // see if it's already cached this frame
4713         if (ent->animcache_vertex3f)
4714         {
4715                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4716                 if (wantnormals || wanttangents)
4717                 {
4718                         if (ent->animcache_normal3f)
4719                                 wantnormals = false;
4720                         if (ent->animcache_svector3f)
4721                                 wanttangents = false;
4722                         if (wantnormals || wanttangents)
4723                         {
4724                                 numvertices = model->surfmesh.num_vertices;
4725                                 if (wantnormals)
4726                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4727                                 if (wanttangents)
4728                                 {
4729                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4730                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4731                                 }
4732                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4733                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4734                         }
4735                 }
4736         }
4737         else
4738         {
4739                 // see if this ent is worth caching
4740                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4741                         return false;
4742                 // get some memory for this entity and generate mesh data
4743                 numvertices = model->surfmesh.num_vertices;
4744                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4745                 if (wantnormals)
4746                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4747                 if (wanttangents)
4748                 {
4749                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4750                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4751                 }
4752                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4753                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4754         }
4755         return true;
4756 }
4757
4758 void R_AnimCache_CacheVisibleEntities(void)
4759 {
4760         int i;
4761         qboolean wantnormals = true;
4762         qboolean wanttangents = !r_showsurfaces.integer;
4763
4764         switch(vid.renderpath)
4765         {
4766         case RENDERPATH_GL20:
4767         case RENDERPATH_D3D9:
4768         case RENDERPATH_D3D10:
4769         case RENDERPATH_D3D11:
4770         case RENDERPATH_GLES2:
4771                 break;
4772         case RENDERPATH_GL11:
4773         case RENDERPATH_GL13:
4774         case RENDERPATH_GLES1:
4775                 wanttangents = false;
4776                 break;
4777         case RENDERPATH_SOFT:
4778                 break;
4779         }
4780
4781         if (r_shownormals.integer)
4782                 wanttangents = wantnormals = true;
4783
4784         // TODO: thread this
4785         // NOTE: R_PrepareRTLights() also caches entities
4786
4787         for (i = 0;i < r_refdef.scene.numentities;i++)
4788                 if (r_refdef.viewcache.entityvisible[i])
4789                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4790 }
4791
4792 //==================================================================================
4793
4794 extern cvar_t r_overheadsprites_pushback;
4795
4796 static void R_View_UpdateEntityLighting (void)
4797 {
4798         int i;
4799         entity_render_t *ent;
4800         vec3_t tempdiffusenormal, avg;
4801         vec_t f, fa, fd, fdd;
4802         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4803
4804         for (i = 0;i < r_refdef.scene.numentities;i++)
4805         {
4806                 ent = r_refdef.scene.entities[i];
4807
4808                 // skip unseen models and models that updated by CSQC
4809                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4810                         continue;
4811
4812                 // skip bsp models
4813                 if (ent->model && ent->model->brush.num_leafs)
4814                 {
4815                         // TODO: use modellight for r_ambient settings on world?
4816                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4817                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4818                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4819                         continue;
4820                 }
4821
4822                 // fetch the lighting from the worldmodel data
4823                 VectorClear(ent->modellight_ambient);
4824                 VectorClear(ent->modellight_diffuse);
4825                 VectorClear(tempdiffusenormal);
4826                 if (ent->flags & RENDER_LIGHT)
4827                 {
4828                         vec3_t org;
4829                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4830
4831                         // complete lightning for lit sprites
4832                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4833                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4834                         {
4835                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4836                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4837                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4838                         }
4839                         else
4840                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4841
4842                         if(ent->flags & RENDER_EQUALIZE)
4843                         {
4844                                 // first fix up ambient lighting...
4845                                 if(r_equalize_entities_minambient.value > 0)
4846                                 {
4847                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4848                                         if(fd > 0)
4849                                         {
4850                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4851                                                 if(fa < r_equalize_entities_minambient.value * fd)
4852                                                 {
4853                                                         // solve:
4854                                                         //   fa'/fd' = minambient
4855                                                         //   fa'+0.25*fd' = fa+0.25*fd
4856                                                         //   ...
4857                                                         //   fa' = fd' * minambient
4858                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4859                                                         //   ...
4860                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4861                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4862                                                         //   ...
4863                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4864                                                         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
4865                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4866                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4867                                                 }
4868                                         }
4869                                 }
4870
4871                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4872                                 {
4873                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4874                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4875                                         f = fa + 0.25 * fd;
4876                                         if(f > 0)
4877                                         {
4878                                                 // adjust brightness and saturation to target
4879                                                 avg[0] = avg[1] = avg[2] = fa / f;
4880                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4881                                                 avg[0] = avg[1] = avg[2] = fd / f;
4882                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4883                                         }
4884                                 }
4885                         }
4886                 }
4887                 else // highly rare
4888                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4889
4890                 // move the light direction into modelspace coordinates for lighting code
4891                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4892                 if(VectorLength2(ent->modellight_lightdir) == 0)
4893                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4894                 VectorNormalize(ent->modellight_lightdir);
4895         }
4896 }
4897
4898 #define MAX_LINEOFSIGHTTRACES 64
4899
4900 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4901 {
4902         int i;
4903         vec3_t boxmins, boxmaxs;
4904         vec3_t start;
4905         vec3_t end;
4906         dp_model_t *model = r_refdef.scene.worldmodel;
4907
4908         if (!model || !model->brush.TraceLineOfSight)
4909                 return true;
4910
4911         // expand the box a little
4912         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4913         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4914         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4915         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4916         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4917         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4918
4919         // return true if eye is inside enlarged box
4920         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4921                 return true;
4922
4923         // try center
4924         VectorCopy(eye, start);
4925         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4926         if (model->brush.TraceLineOfSight(model, start, end))
4927                 return true;
4928
4929         // try various random positions
4930         for (i = 0;i < numsamples;i++)
4931         {
4932                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4933                 if (model->brush.TraceLineOfSight(model, start, end))
4934                         return true;
4935         }
4936
4937         return false;
4938 }
4939
4940
4941 static void R_View_UpdateEntityVisible (void)
4942 {
4943         int i;
4944         int renderimask;
4945         int samples;
4946         entity_render_t *ent;
4947
4948         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4949                 : r_waterstate.hideplayer                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4950                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4951                 :                                                          RENDER_EXTERIORMODEL;
4952         if (!r_drawviewmodel.integer)
4953                 renderimask |= RENDER_VIEWMODEL;
4954         if (!r_drawexteriormodel.integer)
4955                 renderimask |= RENDER_EXTERIORMODEL;
4956         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4957         {
4958                 // worldmodel can check visibility
4959                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4960                 for (i = 0;i < r_refdef.scene.numentities;i++)
4961                 {
4962                         ent = r_refdef.scene.entities[i];
4963                         if (!(ent->flags & renderimask))
4964                         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)))
4965                         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))
4966                                 r_refdef.viewcache.entityvisible[i] = true;
4967                 }
4968         }
4969         else
4970         {
4971                 // no worldmodel or it can't check visibility
4972                 for (i = 0;i < r_refdef.scene.numentities;i++)
4973                 {
4974                         ent = r_refdef.scene.entities[i];
4975                         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));
4976                 }
4977         }
4978         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4979                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4980         {
4981                 for (i = 0;i < r_refdef.scene.numentities;i++)
4982                 {
4983                         if (!r_refdef.viewcache.entityvisible[i])
4984                                 continue;
4985                         ent = r_refdef.scene.entities[i];
4986                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4987                         {
4988                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4989                                 if (samples < 0)
4990                                         continue; // temp entities do pvs only
4991                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4992                                         ent->last_trace_visibility = realtime;
4993                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4994                                         r_refdef.viewcache.entityvisible[i] = 0;
4995                         }
4996                 }
4997         }
4998 }
4999
5000 /// only used if skyrendermasked, and normally returns false
5001 int R_DrawBrushModelsSky (void)
5002 {
5003         int i, sky;
5004         entity_render_t *ent;
5005
5006         sky = false;
5007         for (i = 0;i < r_refdef.scene.numentities;i++)
5008         {
5009                 if (!r_refdef.viewcache.entityvisible[i])
5010                         continue;
5011                 ent = r_refdef.scene.entities[i];
5012                 if (!ent->model || !ent->model->DrawSky)
5013                         continue;
5014                 ent->model->DrawSky(ent);
5015                 sky = true;
5016         }
5017         return sky;
5018 }
5019
5020 static void R_DrawNoModel(entity_render_t *ent);
5021 static void R_DrawModels(void)
5022 {
5023         int i;
5024         entity_render_t *ent;
5025
5026         for (i = 0;i < r_refdef.scene.numentities;i++)
5027         {
5028                 if (!r_refdef.viewcache.entityvisible[i])
5029                         continue;
5030                 ent = r_refdef.scene.entities[i];
5031                 r_refdef.stats.entities++;
5032                 /*
5033                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5034                 {
5035                         vec3_t f, l, u, o;
5036                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5037                         Con_Printf("R_DrawModels\n");
5038                         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]);
5039                         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);
5040                         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);
5041                 }
5042                 */
5043                 if (ent->model && ent->model->Draw != NULL)
5044                         ent->model->Draw(ent);
5045                 else
5046                         R_DrawNoModel(ent);
5047         }
5048 }
5049
5050 static void R_DrawModelsDepth(void)
5051 {
5052         int i;
5053         entity_render_t *ent;
5054
5055         for (i = 0;i < r_refdef.scene.numentities;i++)
5056         {
5057                 if (!r_refdef.viewcache.entityvisible[i])
5058                         continue;
5059                 ent = r_refdef.scene.entities[i];
5060                 if (ent->model && ent->model->DrawDepth != NULL)
5061                         ent->model->DrawDepth(ent);
5062         }
5063 }
5064
5065 static void R_DrawModelsDebug(void)
5066 {
5067         int i;
5068         entity_render_t *ent;
5069
5070         for (i = 0;i < r_refdef.scene.numentities;i++)
5071         {
5072                 if (!r_refdef.viewcache.entityvisible[i])
5073                         continue;
5074                 ent = r_refdef.scene.entities[i];
5075                 if (ent->model && ent->model->DrawDebug != NULL)
5076                         ent->model->DrawDebug(ent);
5077         }
5078 }
5079
5080 static void R_DrawModelsAddWaterPlanes(void)
5081 {
5082         int i;
5083         entity_render_t *ent;
5084
5085         for (i = 0;i < r_refdef.scene.numentities;i++)
5086         {
5087                 if (!r_refdef.viewcache.entityvisible[i])
5088                         continue;
5089                 ent = r_refdef.scene.entities[i];
5090                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5091                         ent->model->DrawAddWaterPlanes(ent);
5092         }
5093 }
5094
5095 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}};
5096
5097 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5098 {
5099         if (r_hdr_irisadaptation.integer)
5100         {
5101                 vec3_t p;
5102                 vec3_t ambient;
5103                 vec3_t diffuse;
5104                 vec3_t diffusenormal;
5105                 vec3_t forward;
5106                 vec_t brightness = 0.0f;
5107                 vec_t goal;
5108                 vec_t current;
5109                 vec_t d;
5110                 int c;
5111                 VectorCopy(r_refdef.view.forward, forward);
5112                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5113                 {
5114                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5115                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5116                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5117                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5118                         d = DotProduct(forward, diffusenormal);
5119                         brightness += VectorLength(ambient);
5120                         if (d > 0)
5121                                 brightness += d * VectorLength(diffuse);
5122                 }
5123                 brightness *= 1.0f / c;
5124                 brightness += 0.00001f; // make sure it's never zero
5125                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5126                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5127                 current = r_hdr_irisadaptation_value.value;
5128                 if (current < goal)
5129                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5130                 else if (current > goal)
5131                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5132                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5133                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5134         }
5135         else if (r_hdr_irisadaptation_value.value != 1.0f)
5136                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5137 }
5138
5139 static void R_View_SetFrustum(const int *scissor)
5140 {
5141         int i;
5142         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5143         vec3_t forward, left, up, origin, v;
5144
5145         if(scissor)
5146         {
5147                 // flipped x coordinates (because x points left here)
5148                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5149                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5150
5151                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5152                 switch(vid.renderpath)
5153                 {
5154                         case RENDERPATH_D3D9:
5155                         case RENDERPATH_D3D10:
5156                         case RENDERPATH_D3D11:
5157                                 // non-flipped y coordinates
5158                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5159                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5160                                 break;
5161                         case RENDERPATH_SOFT:
5162                         case RENDERPATH_GL11:
5163                         case RENDERPATH_GL13:
5164                         case RENDERPATH_GL20:
5165                         case RENDERPATH_GLES1:
5166                         case RENDERPATH_GLES2:
5167                                 // non-flipped y coordinates
5168                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5169                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5170                                 break;
5171                 }
5172         }
5173
5174         // we can't trust r_refdef.view.forward and friends in reflected scenes
5175         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5176
5177 #if 0
5178         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5179         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5180         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5181         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5182         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5183         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5184         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5185         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5186         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5187         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5188         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5189         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5190 #endif
5191
5192 #if 0
5193         zNear = r_refdef.nearclip;
5194         nudge = 1.0 - 1.0 / (1<<23);
5195         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5196         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5197         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5198         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5199         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5200         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5201         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5202         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5203 #endif
5204
5205
5206
5207 #if 0
5208         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5209         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5210         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5211         r_refdef.view.frustum[0].dist = m[15] - m[12];
5212
5213         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5214         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5215         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5216         r_refdef.view.frustum[1].dist = m[15] + m[12];
5217
5218         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5219         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5220         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5221         r_refdef.view.frustum[2].dist = m[15] - m[13];
5222
5223         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5224         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5225         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5226         r_refdef.view.frustum[3].dist = m[15] + m[13];
5227
5228         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5229         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5230         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5231         r_refdef.view.frustum[4].dist = m[15] - m[14];
5232
5233         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5234         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5235         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5236         r_refdef.view.frustum[5].dist = m[15] + m[14];
5237 #endif
5238
5239         if (r_refdef.view.useperspective)
5240         {
5241                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5242                 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]);
5243                 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]);
5244                 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]);
5245                 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]);
5246
5247                 // then the normals from the corners relative to origin
5248                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5249                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5250                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5251                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5252
5253                 // in a NORMAL view, forward cross left == up
5254                 // in a REFLECTED view, forward cross left == down
5255                 // so our cross products above need to be adjusted for a left handed coordinate system
5256                 CrossProduct(forward, left, v);
5257                 if(DotProduct(v, up) < 0)
5258                 {
5259                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5260                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5261                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5262                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5263                 }
5264
5265                 // Leaving those out was a mistake, those were in the old code, and they
5266                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5267                 // I couldn't reproduce it after adding those normalizations. --blub
5268                 VectorNormalize(r_refdef.view.frustum[0].normal);
5269                 VectorNormalize(r_refdef.view.frustum[1].normal);
5270                 VectorNormalize(r_refdef.view.frustum[2].normal);
5271                 VectorNormalize(r_refdef.view.frustum[3].normal);
5272
5273                 // make the corners absolute
5274                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5275                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5276                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5277                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5278
5279                 // one more normal
5280                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5281
5282                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5283                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5284                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5285                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5286                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5287         }
5288         else
5289         {
5290                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5291                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5292                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5293                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5294                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5295                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5296                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5297                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5298                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5299                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5300         }
5301         r_refdef.view.numfrustumplanes = 5;
5302
5303         if (r_refdef.view.useclipplane)
5304         {
5305                 r_refdef.view.numfrustumplanes = 6;
5306                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5307         }
5308
5309         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5310                 PlaneClassify(r_refdef.view.frustum + i);
5311
5312         // LordHavoc: note to all quake engine coders, Quake had a special case
5313         // for 90 degrees which assumed a square view (wrong), so I removed it,
5314         // Quake2 has it disabled as well.
5315
5316         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5317         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5318         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5319         //PlaneClassify(&frustum[0]);
5320
5321         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5322         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5323         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5324         //PlaneClassify(&frustum[1]);
5325
5326         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5327         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5328         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5329         //PlaneClassify(&frustum[2]);
5330
5331         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5332         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5333         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5334         //PlaneClassify(&frustum[3]);
5335
5336         // nearclip plane
5337         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5338         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5339         //PlaneClassify(&frustum[4]);
5340 }
5341
5342 void R_View_UpdateWithScissor(const int *myscissor)
5343 {
5344         R_Main_ResizeViewCache();
5345         R_View_SetFrustum(myscissor);
5346         R_View_WorldVisibility(r_refdef.view.useclipplane);
5347         R_View_UpdateEntityVisible();
5348         R_View_UpdateEntityLighting();
5349         R_AnimCache_CacheVisibleEntities();
5350 }
5351
5352 void R_View_Update(void)
5353 {
5354         R_Main_ResizeViewCache();
5355         R_View_SetFrustum(NULL);
5356         R_View_WorldVisibility(r_refdef.view.useclipplane);
5357         R_View_UpdateEntityVisible();
5358         R_View_UpdateEntityLighting();
5359         R_AnimCache_CacheVisibleEntities();
5360 }
5361
5362 float viewscalefpsadjusted = 1.0f;
5363
5364 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5365 {
5366         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5367         scale = bound(0.03125f, scale, 1.0f);
5368         *outwidth = (int)ceil(width * scale);
5369         *outheight = (int)ceil(height * scale);
5370 }
5371
5372 void R_Mesh_SetMainRenderTargets(void)
5373 {
5374         if (r_bloomstate.fbo_framebuffer)
5375                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5376         else
5377                 R_Mesh_ResetRenderTargets();
5378 }
5379
5380 void R_SetupView(qboolean allowwaterclippingplane)
5381 {
5382         const float *customclipplane = NULL;
5383         float plane[4];
5384         int scaledwidth, scaledheight;
5385         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5386         {
5387                 // LordHavoc: couldn't figure out how to make this approach the
5388                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5389                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5390                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5391                         dist = r_refdef.view.clipplane.dist;
5392                 plane[0] = r_refdef.view.clipplane.normal[0];
5393                 plane[1] = r_refdef.view.clipplane.normal[1];
5394                 plane[2] = r_refdef.view.clipplane.normal[2];
5395                 plane[3] = -dist;
5396                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5397         }
5398
5399         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5400         if (!r_refdef.view.useperspective)
5401                 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);
5402         else if (vid.stencil && r_useinfinitefarclip.integer)
5403                 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);
5404         else
5405                 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);
5406         R_Mesh_SetMainRenderTargets();
5407         R_SetViewport(&r_refdef.view.viewport);
5408         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5409         {
5410                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5411                 float screenplane[4];
5412                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5413                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5414                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5415                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5416                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5417         }
5418 }
5419
5420 void R_EntityMatrix(const matrix4x4_t *matrix)
5421 {
5422         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5423         {
5424                 gl_modelmatrixchanged = false;
5425                 gl_modelmatrix = *matrix;
5426                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5427                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5428                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5429                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5430                 CHECKGLERROR
5431                 switch(vid.renderpath)
5432                 {
5433                 case RENDERPATH_D3D9:
5434 #ifdef SUPPORTD3D
5435                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5436                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5437 #endif
5438                         break;
5439                 case RENDERPATH_D3D10:
5440                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5441                         break;
5442                 case RENDERPATH_D3D11:
5443                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5444                         break;
5445                 case RENDERPATH_GL11:
5446                 case RENDERPATH_GL13:
5447                 case RENDERPATH_GLES1:
5448                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5449                         break;
5450                 case RENDERPATH_SOFT:
5451                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5452                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5453                         break;
5454                 case RENDERPATH_GL20:
5455                 case RENDERPATH_GLES2:
5456                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5457                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5458                         break;
5459                 }
5460         }
5461 }
5462
5463 void R_ResetViewRendering2D(void)
5464 {
5465         r_viewport_t viewport;
5466         DrawQ_Finish();
5467
5468         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5469         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);
5470         R_Mesh_ResetRenderTargets();
5471         R_SetViewport(&viewport);
5472         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5473         GL_Color(1, 1, 1, 1);
5474         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5475         GL_BlendFunc(GL_ONE, GL_ZERO);
5476         GL_ScissorTest(false);
5477         GL_DepthMask(false);
5478         GL_DepthRange(0, 1);
5479         GL_DepthTest(false);
5480         GL_DepthFunc(GL_LEQUAL);
5481         R_EntityMatrix(&identitymatrix);
5482         R_Mesh_ResetTextureState();
5483         GL_PolygonOffset(0, 0);
5484         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5485         switch(vid.renderpath)
5486         {
5487         case RENDERPATH_GL11:
5488         case RENDERPATH_GL13:
5489         case RENDERPATH_GL20:
5490         case RENDERPATH_GLES1:
5491         case RENDERPATH_GLES2:
5492                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5493                 break;
5494         case RENDERPATH_D3D9:
5495         case RENDERPATH_D3D10:
5496         case RENDERPATH_D3D11:
5497         case RENDERPATH_SOFT:
5498                 break;
5499         }
5500         GL_CullFace(GL_NONE);
5501 }
5502
5503 void R_ResetViewRendering3D(void)
5504 {
5505         DrawQ_Finish();
5506
5507         R_SetupView(true);
5508         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5509         GL_Color(1, 1, 1, 1);
5510         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5511         GL_BlendFunc(GL_ONE, GL_ZERO);
5512         GL_ScissorTest(true);
5513         GL_DepthMask(true);
5514         GL_DepthRange(0, 1);
5515         GL_DepthTest(true);
5516         GL_DepthFunc(GL_LEQUAL);
5517         R_EntityMatrix(&identitymatrix);
5518         R_Mesh_ResetTextureState();
5519         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5520         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5521         switch(vid.renderpath)
5522         {
5523         case RENDERPATH_GL11:
5524         case RENDERPATH_GL13:
5525         case RENDERPATH_GL20:
5526         case RENDERPATH_GLES1:
5527         case RENDERPATH_GLES2:
5528                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5529                 break;
5530         case RENDERPATH_D3D9:
5531         case RENDERPATH_D3D10:
5532         case RENDERPATH_D3D11:
5533         case RENDERPATH_SOFT:
5534                 break;
5535         }
5536         GL_CullFace(r_refdef.view.cullface_back);
5537 }
5538
5539 /*
5540 ================
5541 R_RenderView_UpdateViewVectors
5542 ================
5543 */
5544 static void R_RenderView_UpdateViewVectors(void)
5545 {
5546         // break apart the view matrix into vectors for various purposes
5547         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5548         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5549         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5550         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5551         // make an inverted copy of the view matrix for tracking sprites
5552         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5553 }
5554
5555 void R_RenderScene(void);
5556 void R_RenderWaterPlanes(void);
5557
5558 static void R_Water_StartFrame(void)
5559 {
5560         int i;
5561         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5562         r_waterstate_waterplane_t *p;
5563
5564         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5565                 return;
5566
5567         switch(vid.renderpath)
5568         {
5569         case RENDERPATH_GL20:
5570         case RENDERPATH_D3D9:
5571         case RENDERPATH_D3D10:
5572         case RENDERPATH_D3D11:
5573         case RENDERPATH_SOFT:
5574         case RENDERPATH_GLES2:
5575                 break;
5576         case RENDERPATH_GL11:
5577         case RENDERPATH_GL13:
5578         case RENDERPATH_GLES1:
5579                 return;
5580         }
5581
5582         // set waterwidth and waterheight to the water resolution that will be
5583         // used (often less than the screen resolution for faster rendering)
5584         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5585
5586         // calculate desired texture sizes
5587         // can't use water if the card does not support the texture size
5588         if (!r_water.integer || r_showsurfaces.integer)
5589                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5590         else if (vid.support.arb_texture_non_power_of_two)
5591         {
5592                 texturewidth = waterwidth;
5593                 textureheight = waterheight;
5594                 camerawidth = waterwidth;
5595                 cameraheight = waterheight;
5596         }
5597         else
5598         {
5599                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5600                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5601                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5602                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5603         }
5604
5605         // allocate textures as needed
5606         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5607         {
5608                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5609                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5610                 {
5611                         if (p->texture_refraction)
5612                                 R_FreeTexture(p->texture_refraction);
5613                         p->texture_refraction = NULL;
5614                         if (p->texture_reflection)
5615                                 R_FreeTexture(p->texture_reflection);
5616                         p->texture_reflection = NULL;
5617                         if (p->texture_camera)
5618                                 R_FreeTexture(p->texture_camera);
5619                         p->texture_camera = NULL;
5620                 }
5621                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5622                 r_waterstate.texturewidth = texturewidth;
5623                 r_waterstate.textureheight = textureheight;
5624                 r_waterstate.camerawidth = camerawidth;
5625                 r_waterstate.cameraheight = cameraheight;
5626         }
5627
5628         if (r_waterstate.texturewidth)
5629         {
5630                 int scaledwidth, scaledheight;
5631
5632                 r_waterstate.enabled = true;
5633
5634                 // when doing a reduced render (HDR) we want to use a smaller area
5635                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5636                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5637                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5638
5639                 // set up variables that will be used in shader setup
5640                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5641                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5642                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5643                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5644         }
5645
5646         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5647         r_waterstate.numwaterplanes = 0;
5648 }
5649
5650 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5651 {
5652         int planeindex, bestplaneindex, vertexindex;
5653         vec3_t mins, maxs, normal, center, v, n;
5654         vec_t planescore, bestplanescore;
5655         mplane_t plane;
5656         r_waterstate_waterplane_t *p;
5657         texture_t *t = R_GetCurrentTexture(surface->texture);
5658
5659         rsurface.texture = t;
5660         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5661         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5662         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5663                 return;
5664         // average the vertex normals, find the surface bounds (after deformvertexes)
5665         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5666         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5667         VectorCopy(n, normal);
5668         VectorCopy(v, mins);
5669         VectorCopy(v, maxs);
5670         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5671         {
5672                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5673                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5674                 VectorAdd(normal, n, normal);
5675                 mins[0] = min(mins[0], v[0]);
5676                 mins[1] = min(mins[1], v[1]);
5677                 mins[2] = min(mins[2], v[2]);
5678                 maxs[0] = max(maxs[0], v[0]);
5679                 maxs[1] = max(maxs[1], v[1]);
5680                 maxs[2] = max(maxs[2], v[2]);
5681         }
5682         VectorNormalize(normal);
5683         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5684
5685         VectorCopy(normal, plane.normal);
5686         VectorNormalize(plane.normal);
5687         plane.dist = DotProduct(center, plane.normal);
5688         PlaneClassify(&plane);
5689         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5690         {
5691                 // skip backfaces (except if nocullface is set)
5692 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5693 //                      return;
5694                 VectorNegate(plane.normal, plane.normal);
5695                 plane.dist *= -1;
5696                 PlaneClassify(&plane);
5697         }
5698
5699
5700         // find a matching plane if there is one
5701         bestplaneindex = -1;
5702         bestplanescore = 1048576.0f;
5703         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5704         {
5705                 if(p->camera_entity == t->camera_entity)
5706                 {
5707                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5708                         if (bestplaneindex < 0 || bestplanescore > planescore)
5709                         {
5710                                 bestplaneindex = planeindex;
5711                                 bestplanescore = planescore;
5712                         }
5713                 }
5714         }
5715         planeindex = bestplaneindex;
5716         p = r_waterstate.waterplanes + planeindex;
5717
5718         // if this surface does not fit any known plane rendered this frame, add one
5719         if ((planeindex < 0 || bestplanescore > 0.001f) && r_waterstate.numwaterplanes < r_waterstate.maxwaterplanes)
5720         {
5721                 // store the new plane
5722                 planeindex = r_waterstate.numwaterplanes++;
5723                 p = r_waterstate.waterplanes + planeindex;
5724                 p->plane = plane;
5725                 // clear materialflags and pvs
5726                 p->materialflags = 0;
5727                 p->pvsvalid = false;
5728                 p->camera_entity = t->camera_entity;
5729                 VectorCopy(mins, p->mins);
5730                 VectorCopy(maxs, p->maxs);
5731         }
5732         else
5733         {
5734                 // merge mins/maxs when we're adding this surface to the plane
5735                 p->mins[0] = min(p->mins[0], mins[0]);
5736                 p->mins[1] = min(p->mins[1], mins[1]);
5737                 p->mins[2] = min(p->mins[2], mins[2]);
5738                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5739                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5740                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5741         }
5742         // merge this surface's materialflags into the waterplane
5743         p->materialflags |= t->currentmaterialflags;
5744         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5745         {
5746                 // merge this surface's PVS into the waterplane
5747                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5748                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5749                 {
5750                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5751                         p->pvsvalid = true;
5752                 }
5753         }
5754 }
5755
5756 extern cvar_t r_drawparticles;
5757 extern cvar_t r_drawdecals;
5758
5759 static void R_Water_ProcessPlanes(void)
5760 {
5761         int myscissor[4];
5762         r_refdef_view_t originalview;
5763         r_refdef_view_t myview;
5764         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;
5765         r_waterstate_waterplane_t *p;
5766         vec3_t visorigin;
5767
5768         originalview = r_refdef.view;
5769
5770         // lowquality hack, temporarily shut down some cvars and restore afterwards
5771         qualityreduction = r_water_lowquality.integer;
5772         if (qualityreduction > 0)
5773         {
5774                 if (qualityreduction >= 1)
5775                 {
5776                         old_r_shadows = r_shadows.integer;
5777                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5778                         old_r_dlight = r_shadow_realtime_dlight.integer;
5779                         Cvar_SetValueQuick(&r_shadows, 0);
5780                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5781                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5782                 }
5783                 if (qualityreduction >= 2)
5784                 {
5785                         old_r_dynamic = r_dynamic.integer;
5786                         old_r_particles = r_drawparticles.integer;
5787                         old_r_decals = r_drawdecals.integer;
5788                         Cvar_SetValueQuick(&r_dynamic, 0);
5789                         Cvar_SetValueQuick(&r_drawparticles, 0);
5790                         Cvar_SetValueQuick(&r_drawdecals, 0);
5791                 }
5792         }
5793
5794         // make sure enough textures are allocated
5795         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5796         {
5797                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5798                 {
5799                         if (!p->texture_refraction)
5800                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5801                         if (!p->texture_refraction)
5802                                 goto error;
5803                 }
5804                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5805                 {
5806                         if (!p->texture_camera)
5807                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5808                         if (!p->texture_camera)
5809                                 goto error;
5810                 }
5811
5812                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5813                 {
5814                         if (!p->texture_reflection)
5815                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5816                         if (!p->texture_reflection)
5817                                 goto error;
5818                 }
5819         }
5820
5821         // render views
5822         r_refdef.view = originalview;
5823         r_refdef.view.showdebug = false;
5824         r_refdef.view.width = r_waterstate.waterwidth;
5825         r_refdef.view.height = r_waterstate.waterheight;
5826         r_refdef.view.useclipplane = true;
5827         myview = r_refdef.view;
5828         r_waterstate.renderingscene = true;
5829         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5830         {
5831                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5832                 {
5833                         r_refdef.view = myview;
5834                         if(r_water_scissormode.integer)
5835                         {
5836                                 R_SetupView(true);
5837                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5838                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5839                         }
5840
5841                         // render reflected scene and copy into texture
5842                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5843                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5844                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5845                         r_refdef.view.clipplane = p->plane;
5846                         // reverse the cullface settings for this render
5847                         r_refdef.view.cullface_front = GL_FRONT;
5848                         r_refdef.view.cullface_back = GL_BACK;
5849                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5850                         {
5851                                 r_refdef.view.usecustompvs = true;
5852                                 if (p->pvsvalid)
5853                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5854                                 else
5855                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5856                         }
5857
5858                         r_waterstate.hideplayer = r_water_hideplayer.integer >= 2;
5859                         R_ResetViewRendering3D();
5860                         R_ClearScreen(r_refdef.fogenabled);
5861                         if(r_water_scissormode.integer & 2)
5862                                 R_View_UpdateWithScissor(myscissor);
5863                         else
5864                                 R_View_Update();
5865                         if(r_water_scissormode.integer & 1)
5866                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5867                         R_RenderScene();
5868
5869                         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);
5870                         r_waterstate.hideplayer = false;
5871                 }
5872
5873                 // render the normal view scene and copy into texture
5874                 // (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)
5875                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5876                 {
5877                         r_refdef.view = myview;
5878                         if(r_water_scissormode.integer)
5879                         {
5880                                 R_SetupView(true);
5881                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5882                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5883                         }
5884
5885                         r_waterstate.hideplayer = r_water_hideplayer.integer >= 1;
5886
5887                         r_refdef.view.clipplane = p->plane;
5888                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5889                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5890
5891                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5892                         {
5893                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5894                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5895                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5896                                 R_RenderView_UpdateViewVectors();
5897                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5898                                 {
5899                                         r_refdef.view.usecustompvs = true;
5900                                         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);
5901                                 }
5902                         }
5903
5904                         PlaneClassify(&r_refdef.view.clipplane);
5905
5906                         R_ResetViewRendering3D();
5907                         R_ClearScreen(r_refdef.fogenabled);
5908                         if(r_water_scissormode.integer & 2)
5909                                 R_View_UpdateWithScissor(myscissor);
5910                         else
5911                                 R_View_Update();
5912                         if(r_water_scissormode.integer & 1)
5913                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5914                         R_RenderScene();
5915
5916                         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);
5917                         r_waterstate.hideplayer = false;
5918                 }
5919                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5920                 {
5921                         r_refdef.view = myview;
5922
5923                         r_refdef.view.clipplane = p->plane;
5924                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5925                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5926
5927                         r_refdef.view.width = r_waterstate.camerawidth;
5928                         r_refdef.view.height = r_waterstate.cameraheight;
5929                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5930                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5931                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5932                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5933
5934                         if(p->camera_entity)
5935                         {
5936                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5937                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5938                         }
5939
5940                         // note: all of the view is used for displaying... so
5941                         // there is no use in scissoring
5942
5943                         // reverse the cullface settings for this render
5944                         r_refdef.view.cullface_front = GL_FRONT;
5945                         r_refdef.view.cullface_back = GL_BACK;
5946                         // also reverse the view matrix
5947                         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
5948                         R_RenderView_UpdateViewVectors();
5949                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5950                         {
5951                                 r_refdef.view.usecustompvs = true;
5952                                 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);
5953                         }
5954                         
5955                         // camera needs no clipplane
5956                         r_refdef.view.useclipplane = false;
5957
5958                         PlaneClassify(&r_refdef.view.clipplane);
5959
5960                         r_waterstate.hideplayer = false;
5961
5962                         R_ResetViewRendering3D();
5963                         R_ClearScreen(r_refdef.fogenabled);
5964                         R_View_Update();
5965                         R_RenderScene();
5966
5967                         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);
5968                         r_waterstate.hideplayer = false;
5969                 }
5970
5971         }
5972         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5973         r_waterstate.renderingscene = false;
5974         r_refdef.view = originalview;
5975         R_ResetViewRendering3D();
5976         R_ClearScreen(r_refdef.fogenabled);
5977         R_View_Update();
5978         goto finish;
5979 error:
5980         r_refdef.view = originalview;
5981         r_waterstate.renderingscene = false;
5982         Cvar_SetValueQuick(&r_water, 0);
5983         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5984 finish:
5985         // lowquality hack, restore cvars
5986         if (qualityreduction > 0)
5987         {
5988                 if (qualityreduction >= 1)
5989                 {
5990                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5991                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5992                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5993                 }
5994                 if (qualityreduction >= 2)
5995                 {
5996                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5997                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5998                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5999                 }
6000         }
6001 }
6002
6003 void R_Bloom_StartFrame(void)
6004 {
6005         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6006         int viewwidth, viewheight;
6007         textype_t textype;
6008
6009         if (r_viewscale_fpsscaling.integer)
6010         {
6011                 double actualframetime;
6012                 double targetframetime;
6013                 double adjust;
6014                 actualframetime = r_refdef.lastdrawscreentime;
6015                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6016                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6017                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6018                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6019                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6020                 viewscalefpsadjusted += adjust;
6021                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6022         }
6023         else
6024                 viewscalefpsadjusted = 1.0f;
6025
6026         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6027
6028         switch(vid.renderpath)
6029         {
6030         case RENDERPATH_GL20:
6031         case RENDERPATH_D3D9:
6032         case RENDERPATH_D3D10:
6033         case RENDERPATH_D3D11:
6034         case RENDERPATH_SOFT:
6035         case RENDERPATH_GLES2:
6036                 break;
6037         case RENDERPATH_GL11:
6038         case RENDERPATH_GL13:
6039         case RENDERPATH_GLES1:
6040                 return;
6041         }
6042
6043         // set bloomwidth and bloomheight to the bloom resolution that will be
6044         // used (often less than the screen resolution for faster rendering)
6045         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6046         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
6047         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
6048         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
6049         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
6050
6051         // calculate desired texture sizes
6052         if (vid.support.arb_texture_non_power_of_two)
6053         {
6054                 screentexturewidth = vid.width;
6055                 screentextureheight = vid.height;
6056                 bloomtexturewidth = r_bloomstate.bloomwidth;
6057                 bloomtextureheight = r_bloomstate.bloomheight;
6058         }
6059         else
6060         {
6061                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
6062                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
6063                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
6064                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
6065         }
6066
6067         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))
6068         {
6069                 Cvar_SetValueQuick(&r_hdr, 0);
6070                 Cvar_SetValueQuick(&r_bloom, 0);
6071                 Cvar_SetValueQuick(&r_motionblur, 0);
6072                 Cvar_SetValueQuick(&r_damageblur, 0);
6073         }
6074
6075         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)
6076                 screentexturewidth = screentextureheight = 0;
6077         if (!r_hdr.integer && !r_bloom.integer)
6078                 bloomtexturewidth = bloomtextureheight = 0;
6079
6080         textype = TEXTYPE_COLORBUFFER;
6081         switch (vid.renderpath)
6082         {
6083         case RENDERPATH_GL20:
6084         case RENDERPATH_GLES2:
6085                 if (vid.support.ext_framebuffer_object)
6086                 {
6087                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6088                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6089                 }
6090                 break;
6091         case RENDERPATH_GL11:
6092         case RENDERPATH_GL13:
6093         case RENDERPATH_GLES1:
6094         case RENDERPATH_D3D9:
6095         case RENDERPATH_D3D10:
6096         case RENDERPATH_D3D11:
6097         case RENDERPATH_SOFT:
6098                 break;
6099         }
6100
6101         // allocate textures as needed
6102         if (r_bloomstate.screentexturewidth != screentexturewidth
6103          || r_bloomstate.screentextureheight != screentextureheight
6104          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6105          || r_bloomstate.bloomtextureheight != bloomtextureheight
6106          || r_bloomstate.texturetype != textype
6107          || r_bloomstate.viewfbo != r_viewfbo.integer)
6108         {
6109                 if (r_bloomstate.texture_bloom)
6110                         R_FreeTexture(r_bloomstate.texture_bloom);
6111                 r_bloomstate.texture_bloom = NULL;
6112                 if (r_bloomstate.texture_screen)
6113                         R_FreeTexture(r_bloomstate.texture_screen);
6114                 r_bloomstate.texture_screen = NULL;
6115                 if (r_bloomstate.fbo_framebuffer)
6116                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6117                 r_bloomstate.fbo_framebuffer = 0;
6118                 if (r_bloomstate.texture_framebuffercolor)
6119                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6120                 r_bloomstate.texture_framebuffercolor = NULL;
6121                 if (r_bloomstate.texture_framebufferdepth)
6122                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6123                 r_bloomstate.texture_framebufferdepth = NULL;
6124                 r_bloomstate.screentexturewidth = screentexturewidth;
6125                 r_bloomstate.screentextureheight = screentextureheight;
6126                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6127                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6128                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6129                 {
6130                         // FIXME: choose depth bits based on a cvar
6131                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6132                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6133                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6134                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6135 #ifndef USE_GLES2
6136                         // render depth into one texture and normalmap into the other
6137                         if (qglDrawBuffer)
6138                         {
6139                                 int status;
6140                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6141                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6142                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6143                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6144                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6145                         }
6146 #endif
6147                 }
6148                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6149                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6150                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6151                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6152                 r_bloomstate.viewfbo = r_viewfbo.integer;
6153                 r_bloomstate.texturetype = textype;
6154         }
6155
6156         // when doing a reduced render (HDR) we want to use a smaller area
6157         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6158         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6159         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6160         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6161         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6162
6163         // set up a texcoord array for the full resolution screen image
6164         // (we have to keep this around to copy back during final render)
6165         r_bloomstate.screentexcoord2f[0] = 0;
6166         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6167         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6168         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6169         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6170         r_bloomstate.screentexcoord2f[5] = 0;
6171         r_bloomstate.screentexcoord2f[6] = 0;
6172         r_bloomstate.screentexcoord2f[7] = 0;
6173
6174         // set up a texcoord array for the reduced resolution bloom image
6175         // (which will be additive blended over the screen image)
6176         r_bloomstate.bloomtexcoord2f[0] = 0;
6177         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6179         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6181         r_bloomstate.bloomtexcoord2f[5] = 0;
6182         r_bloomstate.bloomtexcoord2f[6] = 0;
6183         r_bloomstate.bloomtexcoord2f[7] = 0;
6184
6185         switch(vid.renderpath)
6186         {
6187         case RENDERPATH_GL11:
6188         case RENDERPATH_GL13:
6189         case RENDERPATH_GL20:
6190         case RENDERPATH_SOFT:
6191         case RENDERPATH_GLES1:
6192         case RENDERPATH_GLES2:
6193                 break;
6194         case RENDERPATH_D3D9:
6195         case RENDERPATH_D3D10:
6196         case RENDERPATH_D3D11:
6197                 {
6198                         int i;
6199                         for (i = 0;i < 4;i++)
6200                         {
6201                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6202                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6203                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6204                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6205                         }
6206                 }
6207                 break;
6208         }
6209
6210         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6211         {
6212                 r_bloomstate.enabled = true;
6213                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6214         }
6215
6216         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6217
6218         if (r_bloomstate.fbo_framebuffer)
6219                 r_refdef.view.clear = true;
6220 }
6221
6222 void R_Bloom_CopyBloomTexture(float colorscale)
6223 {
6224         r_refdef.stats.bloom++;
6225
6226         // scale down screen texture to the bloom texture size
6227         CHECKGLERROR
6228         R_Mesh_SetMainRenderTargets();
6229         R_SetViewport(&r_bloomstate.viewport);
6230         GL_BlendFunc(GL_ONE, GL_ZERO);
6231         GL_Color(colorscale, colorscale, colorscale, 1);
6232         // 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...
6233         switch(vid.renderpath)
6234         {
6235         case RENDERPATH_GL11:
6236         case RENDERPATH_GL13:
6237         case RENDERPATH_GL20:
6238         case RENDERPATH_GLES1:
6239         case RENDERPATH_GLES2:
6240         case RENDERPATH_SOFT:
6241                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6242                 break;
6243         case RENDERPATH_D3D9:
6244         case RENDERPATH_D3D10:
6245         case RENDERPATH_D3D11:
6246                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6247                 break;
6248         }
6249         // TODO: do boxfilter scale-down in shader?
6250         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6251         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6252         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6253
6254         // we now have a bloom image in the framebuffer
6255         // copy it into the bloom image texture for later processing
6256         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6257         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6258 }
6259
6260 void R_Bloom_CopyHDRTexture(void)
6261 {
6262         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6263         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6264 }
6265
6266 void R_Bloom_MakeTexture(void)
6267 {
6268         int x, range, dir;
6269         float xoffset, yoffset, r, brighten;
6270
6271         r_refdef.stats.bloom++;
6272
6273         R_ResetViewRendering2D();
6274
6275         // we have a bloom image in the framebuffer
6276         CHECKGLERROR
6277         R_SetViewport(&r_bloomstate.viewport);
6278
6279         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6280         {
6281                 x *= 2;
6282                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6283                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6284                 GL_Color(r,r,r,1);
6285                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6286                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6287                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6288                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6289
6290                 // copy the vertically blurred bloom view to a texture
6291                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6292                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6293         }
6294
6295         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6296         brighten = r_bloom_brighten.value;
6297         if (r_bloomstate.hdr)
6298                 brighten *= r_hdr_range.value;
6299         brighten = sqrt(brighten);
6300         if(range >= 1)
6301                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6302         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6303
6304         for (dir = 0;dir < 2;dir++)
6305         {
6306                 // blend on at multiple vertical offsets to achieve a vertical blur
6307                 // TODO: do offset blends using GLSL
6308                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6309                 GL_BlendFunc(GL_ONE, GL_ZERO);
6310                 for (x = -range;x <= range;x++)
6311                 {
6312                         if (!dir){xoffset = 0;yoffset = x;}
6313                         else {xoffset = x;yoffset = 0;}
6314                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6315                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6316                         // compute a texcoord array with the specified x and y offset
6317                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6318                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6319                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6320                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6321                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6322                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6323                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6324                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6325                         // this r value looks like a 'dot' particle, fading sharply to
6326                         // black at the edges
6327                         // (probably not realistic but looks good enough)
6328                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6329                         //r = brighten/(range*2+1);
6330                         r = brighten / (range * 2 + 1);
6331                         if(range >= 1)
6332                                 r *= (1 - x*x/(float)(range*range));
6333                         GL_Color(r, r, r, 1);
6334                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6335                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6336                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6337                         GL_BlendFunc(GL_ONE, GL_ONE);
6338                 }
6339
6340                 // copy the vertically blurred bloom view to a texture
6341                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6342                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6343         }
6344 }
6345
6346 void R_HDR_RenderBloomTexture(void)
6347 {
6348         int oldwidth, oldheight;
6349         float oldcolorscale;
6350         qboolean oldwaterstate;
6351
6352         oldwaterstate = r_waterstate.enabled;
6353         oldcolorscale = r_refdef.view.colorscale;
6354         oldwidth = r_refdef.view.width;
6355         oldheight = r_refdef.view.height;
6356         r_refdef.view.width = r_bloomstate.bloomwidth;
6357         r_refdef.view.height = r_bloomstate.bloomheight;
6358
6359         if(r_hdr.integer < 2)
6360                 r_waterstate.enabled = false;
6361
6362         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6363         // TODO: add exposure compensation features
6364         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6365
6366         r_refdef.view.showdebug = false;
6367         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6368
6369         R_ResetViewRendering3D();
6370
6371         R_ClearScreen(r_refdef.fogenabled);
6372         if (r_timereport_active)
6373                 R_TimeReport("HDRclear");
6374
6375         R_View_Update();
6376         if (r_timereport_active)
6377                 R_TimeReport("visibility");
6378
6379         // only do secondary renders with HDR if r_hdr is 2 or higher
6380         r_waterstate.numwaterplanes = 0;
6381         if (r_waterstate.enabled)
6382                 R_RenderWaterPlanes();
6383
6384         r_refdef.view.showdebug = true;
6385         R_RenderScene();
6386         r_waterstate.numwaterplanes = 0;
6387
6388         R_ResetViewRendering2D();
6389
6390         R_Bloom_CopyHDRTexture();
6391         R_Bloom_MakeTexture();
6392
6393         // restore the view settings
6394         r_waterstate.enabled = oldwaterstate;
6395         r_refdef.view.width = oldwidth;
6396         r_refdef.view.height = oldheight;
6397         r_refdef.view.colorscale = oldcolorscale;
6398
6399         R_ResetViewRendering3D();
6400
6401         R_ClearScreen(r_refdef.fogenabled);
6402         if (r_timereport_active)
6403                 R_TimeReport("viewclear");
6404 }
6405
6406 static void R_BlendView(void)
6407 {
6408         unsigned int permutation;
6409         float uservecs[4][4];
6410
6411         switch (vid.renderpath)
6412         {
6413         case RENDERPATH_GL20:
6414         case RENDERPATH_D3D9:
6415         case RENDERPATH_D3D10:
6416         case RENDERPATH_D3D11:
6417         case RENDERPATH_SOFT:
6418         case RENDERPATH_GLES2:
6419                 permutation =
6420                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6421                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6422                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6423                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6424                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6425
6426                 if (r_bloomstate.texture_screen)
6427                 {
6428                         // make sure the buffer is available
6429                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6430
6431                         R_ResetViewRendering2D();
6432                         R_Mesh_SetMainRenderTargets();
6433
6434                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6435                         {
6436                                 // declare variables
6437                                 float blur_factor, blur_mouseaccel, blur_velocity;
6438                                 static float blur_average; 
6439                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6440
6441                                 // set a goal for the factoring
6442                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6443                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6444                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6445                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6446                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6447                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6448
6449                                 // from the goal, pick an averaged value between goal and last value
6450                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6451                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6452                                 
6453                                 // enforce minimum amount of blur 
6454                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6455                                 
6456                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6457
6458                                 // calculate values into a standard alpha
6459                                 cl.motionbluralpha = 1 - exp(-
6460                                                 (
6461                                                  (r_motionblur.value * blur_factor / 80)
6462                                                  +
6463                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6464                                                 )
6465                                                 /
6466                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6467                                           );
6468                                 
6469                                 // randomization for the blur value to combat persistent ghosting
6470                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6471                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6472                                 
6473                                 // apply the blur
6474                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6475                                 {
6476                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6477                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6478                                         switch(vid.renderpath)
6479                                         {
6480                                         case RENDERPATH_GL11:
6481                                         case RENDERPATH_GL13:
6482                                         case RENDERPATH_GL20:
6483                                         case RENDERPATH_GLES1:
6484                                         case RENDERPATH_GLES2:
6485                                         case RENDERPATH_SOFT:
6486                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6487                                                 break;
6488                                         case RENDERPATH_D3D9:
6489                                         case RENDERPATH_D3D10:
6490                                         case RENDERPATH_D3D11:
6491                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6492                                                 break;
6493                                         }
6494                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6495                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6496                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6497                                 }
6498                                 
6499                                 // updates old view angles for next pass 
6500                                 VectorCopy(cl.viewangles, blur_oldangles);
6501                         }
6502
6503                         // copy view into the screen texture
6504                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6505                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6506                 }
6507                 else if (!r_bloomstate.texture_bloom)
6508                 {
6509                         // we may still have to do view tint...
6510                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6511                         {
6512                                 // apply a color tint to the whole view
6513                                 R_ResetViewRendering2D();
6514                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6515                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6516                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6517                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6518                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6519                         }
6520                         break; // no screen processing, no bloom, skip it
6521                 }
6522
6523                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6524                 {
6525                         // render simple bloom effect
6526                         // copy the screen and shrink it and darken it for the bloom process
6527                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6528                         // make the bloom texture
6529                         R_Bloom_MakeTexture();
6530                 }
6531
6532 #if _MSC_VER >= 1400
6533 #define sscanf sscanf_s
6534 #endif
6535                 memset(uservecs, 0, sizeof(uservecs));
6536                 if (r_glsl_postprocess_uservec1_enable.integer)
6537                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6538                 if (r_glsl_postprocess_uservec2_enable.integer)
6539                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6540                 if (r_glsl_postprocess_uservec3_enable.integer)
6541                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6542                 if (r_glsl_postprocess_uservec4_enable.integer)
6543                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6544
6545                 R_ResetViewRendering2D();
6546                 GL_Color(1, 1, 1, 1);
6547                 GL_BlendFunc(GL_ONE, GL_ZERO);
6548
6549                 switch(vid.renderpath)
6550                 {
6551                 case RENDERPATH_GL20:
6552                 case RENDERPATH_GLES2:
6553                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6554                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6555                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6556                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6557                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6558                         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]);
6559                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6560                         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]);
6561                         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]);
6562                         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]);
6563                         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]);
6564                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6565                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6566                         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);
6567                         break;
6568                 case RENDERPATH_D3D9:
6569 #ifdef SUPPORTD3D
6570                         // 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...
6571                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6572                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6573                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6574                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6575                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6576                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6577                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6578                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6579                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6580                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6581                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6582                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6583                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6584                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6585 #endif
6586                         break;
6587                 case RENDERPATH_D3D10:
6588                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6589                         break;
6590                 case RENDERPATH_D3D11:
6591                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6592                         break;
6593                 case RENDERPATH_SOFT:
6594                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6595                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6596                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6597                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6598                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6599                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6600                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6601                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6602                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6603                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6604                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6605                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6606                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6607                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6608                         break;
6609                 default:
6610                         break;
6611                 }
6612                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6613                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6614                 break;
6615         case RENDERPATH_GL11:
6616         case RENDERPATH_GL13:
6617         case RENDERPATH_GLES1:
6618                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6619                 {
6620                         // apply a color tint to the whole view
6621                         R_ResetViewRendering2D();
6622                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6623                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6624                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6625                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6626                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6627                 }
6628                 break;
6629         }
6630 }
6631
6632 matrix4x4_t r_waterscrollmatrix;
6633
6634 void R_UpdateFog(void) // needs to be called before HDR subrender too, as that changes colorscale!
6635 {
6636         // Nehahra fog
6637         if (gamemode == GAME_NEHAHRA)
6638         {
6639                 if (gl_fogenable.integer)
6640                 {
6641                         r_refdef.oldgl_fogenable = true;
6642                         r_refdef.fog_density = gl_fogdensity.value;
6643                         r_refdef.fog_red = gl_fogred.value;
6644                         r_refdef.fog_green = gl_foggreen.value;
6645                         r_refdef.fog_blue = gl_fogblue.value;
6646                         r_refdef.fog_alpha = 1;
6647                         r_refdef.fog_start = 0;
6648                         r_refdef.fog_end = gl_skyclip.value;
6649                         r_refdef.fog_height = 1<<30;
6650                         r_refdef.fog_fadedepth = 128;
6651                 }
6652                 else if (r_refdef.oldgl_fogenable)
6653                 {
6654                         r_refdef.oldgl_fogenable = false;
6655                         r_refdef.fog_density = 0;
6656                         r_refdef.fog_red = 0;
6657                         r_refdef.fog_green = 0;
6658                         r_refdef.fog_blue = 0;
6659                         r_refdef.fog_alpha = 0;
6660                         r_refdef.fog_start = 0;
6661                         r_refdef.fog_end = 0;
6662                         r_refdef.fog_height = 1<<30;
6663                         r_refdef.fog_fadedepth = 128;
6664                 }
6665         }
6666
6667         // fog parms
6668         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6669         r_refdef.fog_start = max(0, r_refdef.fog_start);
6670         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6671
6672         if (r_refdef.fog_density && r_drawfog.integer)
6673         {
6674                 r_refdef.fogenabled = true;
6675                 // this is the point where the fog reaches 0.9986 alpha, which we
6676                 // consider a good enough cutoff point for the texture
6677                 // (0.9986 * 256 == 255.6)
6678                 if (r_fog_exp2.integer)
6679                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6680                 else
6681                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6682                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6683                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6684                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6685                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6686                         R_BuildFogHeightTexture();
6687                 // fog color was already set
6688                 // update the fog texture
6689                 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)
6690                         R_BuildFogTexture();
6691                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6692                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6693         }
6694         else
6695                 r_refdef.fogenabled = false;
6696
6697         // fog color
6698         if (r_refdef.fog_density)
6699         {
6700                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6701                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6702                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6703
6704                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6705                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6706                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6707                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6708
6709                 {
6710                         vec3_t fogvec;
6711                         VectorCopy(r_refdef.fogcolor, fogvec);
6712                         //   color.rgb *= ContrastBoost * SceneBrightness;
6713                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6714                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6715                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6716                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6717                 }
6718         }
6719 }
6720
6721 void R_UpdateVariables(void)
6722 {
6723         R_Textures_Frame();
6724
6725         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6726
6727         r_refdef.farclip = r_farclip_base.value;
6728         if (r_refdef.scene.worldmodel)
6729                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6730         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6731
6732         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6733                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6734         r_refdef.polygonfactor = 0;
6735         r_refdef.polygonoffset = 0;
6736         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6737         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6738
6739         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6740         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6741         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6742         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6743         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6744         if (FAKELIGHT_ENABLED)
6745         {
6746                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6747         }
6748         if (r_showsurfaces.integer)
6749         {
6750                 r_refdef.scene.rtworld = false;
6751                 r_refdef.scene.rtworldshadows = false;
6752                 r_refdef.scene.rtdlight = false;
6753                 r_refdef.scene.rtdlightshadows = false;
6754                 r_refdef.lightmapintensity = 0;
6755         }
6756
6757         switch(vid.renderpath)
6758         {
6759         case RENDERPATH_GL20:
6760         case RENDERPATH_D3D9:
6761         case RENDERPATH_D3D10:
6762         case RENDERPATH_D3D11:
6763         case RENDERPATH_SOFT:
6764         case RENDERPATH_GLES2:
6765                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6766                 {
6767                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6768                         {
6769                                 // build GLSL gamma texture
6770 #define RAMPWIDTH 256
6771                                 unsigned short ramp[RAMPWIDTH * 3];
6772                                 unsigned char rampbgr[RAMPWIDTH][4];
6773                                 int i;
6774
6775                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6776
6777                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6778                                 for(i = 0; i < RAMPWIDTH; ++i)
6779                                 {
6780                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6781                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6782                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6783                                         rampbgr[i][3] = 0;
6784                                 }
6785                                 if (r_texture_gammaramps)
6786                                 {
6787                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6788                                 }
6789                                 else
6790                                 {
6791                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6792                                 }
6793                         }
6794                 }
6795                 else
6796                 {
6797                         // remove GLSL gamma texture
6798                 }
6799                 break;
6800         case RENDERPATH_GL11:
6801         case RENDERPATH_GL13:
6802         case RENDERPATH_GLES1:
6803                 break;
6804         }
6805 }
6806
6807 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6808 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6809 /*
6810 ================
6811 R_SelectScene
6812 ================
6813 */
6814 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6815         if( scenetype != r_currentscenetype ) {
6816                 // store the old scenetype
6817                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6818                 r_currentscenetype = scenetype;
6819                 // move in the new scene
6820                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6821         }
6822 }
6823
6824 /*
6825 ================
6826 R_GetScenePointer
6827 ================
6828 */
6829 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6830 {
6831         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6832         if( scenetype == r_currentscenetype ) {
6833                 return &r_refdef.scene;
6834         } else {
6835                 return &r_scenes_store[ scenetype ];
6836         }
6837 }
6838
6839 int R_SortEntities_Compare(const void *ap, const void *bp)
6840 {
6841         const entity_render_t *a = *(const entity_render_t **)ap;
6842         const entity_render_t *b = *(const entity_render_t **)bp;
6843
6844         // 1. compare model
6845         if(a->model < b->model)
6846                 return -1;
6847         if(a->model > b->model)
6848                 return +1;
6849
6850         // 2. compare skin
6851         // TODO possibly calculate the REAL skinnum here first using
6852         // skinscenes?
6853         if(a->skinnum < b->skinnum)
6854                 return -1;
6855         if(a->skinnum > b->skinnum)
6856                 return +1;
6857
6858         // everything we compared is equal
6859         return 0;
6860 }
6861 void R_SortEntities(void)
6862 {
6863         // below or equal 2 ents, sorting never gains anything
6864         if(r_refdef.scene.numentities <= 2)
6865                 return;
6866         // sort
6867         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6868 }
6869
6870 /*
6871 ================
6872 R_RenderView
6873 ================
6874 */
6875 int dpsoftrast_test;
6876 extern void R_Shadow_UpdateBounceGridTexture(void);
6877 extern cvar_t r_shadow_bouncegrid;
6878 void R_RenderView(void)
6879 {
6880         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6881
6882         dpsoftrast_test = r_test.integer;
6883
6884         if (r_timereport_active)
6885                 R_TimeReport("start");
6886         r_textureframe++; // used only by R_GetCurrentTexture
6887         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6888
6889         if(R_CompileShader_CheckStaticParms())
6890                 R_GLSL_Restart_f();
6891
6892         if (!r_drawentities.integer)
6893                 r_refdef.scene.numentities = 0;
6894         else if (r_sortentities.integer)
6895                 R_SortEntities();
6896
6897         R_AnimCache_ClearCache();
6898         R_FrameData_NewFrame();
6899
6900         /* adjust for stereo display */
6901         if(R_Stereo_Active())
6902         {
6903                 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);
6904                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6905         }
6906
6907         if (r_refdef.view.isoverlay)
6908         {
6909                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6910                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6911                 R_TimeReport("depthclear");
6912
6913                 r_refdef.view.showdebug = false;
6914
6915                 r_waterstate.enabled = false;
6916                 r_waterstate.numwaterplanes = 0;
6917
6918                 R_RenderScene();
6919
6920                 r_refdef.view.matrix = originalmatrix;
6921
6922                 CHECKGLERROR
6923                 return;
6924         }
6925
6926         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6927         {
6928                 r_refdef.view.matrix = originalmatrix;
6929                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6930         }
6931
6932         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6933
6934         R_RenderView_UpdateViewVectors();
6935
6936         R_Shadow_UpdateWorldLightSelection();
6937
6938         R_Bloom_StartFrame();
6939         R_Water_StartFrame();
6940
6941         CHECKGLERROR
6942         if (r_timereport_active)
6943                 R_TimeReport("viewsetup");
6944
6945         R_ResetViewRendering3D();
6946
6947         if (r_refdef.view.clear || r_refdef.fogenabled)
6948         {
6949                 R_ClearScreen(r_refdef.fogenabled);
6950                 if (r_timereport_active)
6951                         R_TimeReport("viewclear");
6952         }
6953         r_refdef.view.clear = true;
6954
6955         // this produces a bloom texture to be used in R_BlendView() later
6956         if (r_bloomstate.hdr)
6957         {
6958                 R_HDR_RenderBloomTexture();
6959                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6960                 r_textureframe++; // used only by R_GetCurrentTexture
6961         }
6962
6963         r_refdef.view.showdebug = true;
6964
6965         R_View_Update();
6966         if (r_timereport_active)
6967                 R_TimeReport("visibility");
6968
6969         R_Shadow_UpdateBounceGridTexture();
6970         if (r_timereport_active && r_shadow_bouncegrid.integer)
6971                 R_TimeReport("bouncegrid");
6972
6973         r_waterstate.numwaterplanes = 0;
6974         if (r_waterstate.enabled)
6975                 R_RenderWaterPlanes();
6976
6977         R_RenderScene();
6978         r_waterstate.numwaterplanes = 0;
6979
6980         R_BlendView();
6981         if (r_timereport_active)
6982                 R_TimeReport("blendview");
6983
6984         GL_Scissor(0, 0, vid.width, vid.height);
6985         GL_ScissorTest(false);
6986
6987         r_refdef.view.matrix = originalmatrix;
6988
6989         CHECKGLERROR
6990 }
6991
6992 void R_RenderWaterPlanes(void)
6993 {
6994         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6995         {
6996                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6997                 if (r_timereport_active)
6998                         R_TimeReport("waterworld");
6999         }
7000
7001         // don't let sound skip if going slow
7002         if (r_refdef.scene.extraupdate)
7003                 S_ExtraUpdate ();
7004
7005         R_DrawModelsAddWaterPlanes();
7006         if (r_timereport_active)
7007                 R_TimeReport("watermodels");
7008
7009         if (r_waterstate.numwaterplanes)
7010         {
7011                 R_Water_ProcessPlanes();
7012                 if (r_timereport_active)
7013                         R_TimeReport("waterscenes");
7014         }
7015 }
7016
7017 extern void R_DrawLightningBeams (void);
7018 extern void VM_CL_AddPolygonsToMeshQueue (void);
7019 extern void R_DrawPortals (void);
7020 extern cvar_t cl_locs_show;
7021 static void R_DrawLocs(void);
7022 static void R_DrawEntityBBoxes(void);
7023 static void R_DrawModelDecals(void);
7024 extern void R_DrawModelShadows(void);
7025 extern void R_DrawModelShadowMaps(void);
7026 extern cvar_t cl_decals_newsystem;
7027 extern qboolean r_shadow_usingdeferredprepass;
7028 void R_RenderScene(void)
7029 {
7030         qboolean shadowmapping = false;
7031
7032         if (r_timereport_active)
7033                 R_TimeReport("beginscene");
7034
7035         r_refdef.stats.renders++;
7036
7037         R_UpdateFog();
7038
7039         // don't let sound skip if going slow
7040         if (r_refdef.scene.extraupdate)
7041                 S_ExtraUpdate ();
7042
7043         R_MeshQueue_BeginScene();
7044
7045         R_SkyStartFrame();
7046
7047         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);
7048
7049         if (r_timereport_active)
7050                 R_TimeReport("skystartframe");
7051
7052         if (cl.csqc_vidvars.drawworld)
7053         {
7054                 // don't let sound skip if going slow
7055                 if (r_refdef.scene.extraupdate)
7056                         S_ExtraUpdate ();
7057
7058                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7059                 {
7060                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7061                         if (r_timereport_active)
7062                                 R_TimeReport("worldsky");
7063                 }
7064
7065                 if (R_DrawBrushModelsSky() && r_timereport_active)
7066                         R_TimeReport("bmodelsky");
7067
7068                 if (skyrendermasked && skyrenderlater)
7069                 {
7070                         // we have to force off the water clipping plane while rendering sky
7071                         R_SetupView(false);
7072                         R_Sky();
7073                         R_SetupView(true);
7074                         if (r_timereport_active)
7075                                 R_TimeReport("sky");
7076                 }
7077         }
7078
7079         R_Shadow_PrepareLights();
7080         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7081                 R_Shadow_PrepareModelShadows();
7082         if (r_timereport_active)
7083                 R_TimeReport("preparelights");
7084
7085         if (R_Shadow_ShadowMappingEnabled())
7086                 shadowmapping = true;
7087
7088         if (r_shadow_usingdeferredprepass)
7089                 R_Shadow_DrawPrepass();
7090
7091         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7092         {
7093                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7094                 if (r_timereport_active)
7095                         R_TimeReport("worlddepth");
7096         }
7097         if (r_depthfirst.integer >= 2)
7098         {
7099                 R_DrawModelsDepth();
7100                 if (r_timereport_active)
7101                         R_TimeReport("modeldepth");
7102         }
7103
7104         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7105         {
7106                 R_DrawModelShadowMaps();
7107                 R_ResetViewRendering3D();
7108                 // don't let sound skip if going slow
7109                 if (r_refdef.scene.extraupdate)
7110                         S_ExtraUpdate ();
7111         }
7112
7113         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7114         {
7115                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7116                 if (r_timereport_active)
7117                         R_TimeReport("world");
7118         }
7119
7120         // don't let sound skip if going slow
7121         if (r_refdef.scene.extraupdate)
7122                 S_ExtraUpdate ();
7123
7124         R_DrawModels();
7125         if (r_timereport_active)
7126                 R_TimeReport("models");
7127
7128         // don't let sound skip if going slow
7129         if (r_refdef.scene.extraupdate)
7130                 S_ExtraUpdate ();
7131
7132         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7133         {
7134                 R_DrawModelShadows();
7135                 R_ResetViewRendering3D();
7136                 // don't let sound skip if going slow
7137                 if (r_refdef.scene.extraupdate)
7138                         S_ExtraUpdate ();
7139         }
7140
7141         if (!r_shadow_usingdeferredprepass)
7142         {
7143                 R_Shadow_DrawLights();
7144                 if (r_timereport_active)
7145                         R_TimeReport("rtlights");
7146         }
7147
7148         // don't let sound skip if going slow
7149         if (r_refdef.scene.extraupdate)
7150                 S_ExtraUpdate ();
7151
7152         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7153         {
7154                 R_DrawModelShadows();
7155                 R_ResetViewRendering3D();
7156                 // don't let sound skip if going slow
7157                 if (r_refdef.scene.extraupdate)
7158                         S_ExtraUpdate ();
7159         }
7160
7161         if (cl.csqc_vidvars.drawworld)
7162         {
7163                 if (cl_decals_newsystem.integer)
7164                 {
7165                         R_DrawModelDecals();
7166                         if (r_timereport_active)
7167                                 R_TimeReport("modeldecals");
7168                 }
7169                 else
7170                 {
7171                         R_DrawDecals();
7172                         if (r_timereport_active)
7173                                 R_TimeReport("decals");
7174                 }
7175
7176                 R_DrawParticles();
7177                 if (r_timereport_active)
7178                         R_TimeReport("particles");
7179
7180                 R_DrawExplosions();
7181                 if (r_timereport_active)
7182                         R_TimeReport("explosions");
7183
7184                 R_DrawLightningBeams();
7185                 if (r_timereport_active)
7186                         R_TimeReport("lightning");
7187         }
7188
7189         VM_CL_AddPolygonsToMeshQueue();
7190
7191         if (r_refdef.view.showdebug)
7192         {
7193                 if (cl_locs_show.integer)
7194                 {
7195                         R_DrawLocs();
7196                         if (r_timereport_active)
7197                                 R_TimeReport("showlocs");
7198                 }
7199
7200                 if (r_drawportals.integer)
7201                 {
7202                         R_DrawPortals();
7203                         if (r_timereport_active)
7204                                 R_TimeReport("portals");
7205                 }
7206
7207                 if (r_showbboxes.value > 0)
7208                 {
7209                         R_DrawEntityBBoxes();
7210                         if (r_timereport_active)
7211                                 R_TimeReport("bboxes");
7212                 }
7213         }
7214
7215         if (r_transparent.integer)
7216         {
7217                 R_MeshQueue_RenderTransparent();
7218                 if (r_timereport_active)
7219                         R_TimeReport("drawtrans");
7220         }
7221
7222         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))
7223         {
7224                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7225                 if (r_timereport_active)
7226                         R_TimeReport("worlddebug");
7227                 R_DrawModelsDebug();
7228                 if (r_timereport_active)
7229                         R_TimeReport("modeldebug");
7230         }
7231
7232         if (cl.csqc_vidvars.drawworld)
7233         {
7234                 R_Shadow_DrawCoronas();
7235                 if (r_timereport_active)
7236                         R_TimeReport("coronas");
7237         }
7238
7239 #if 0
7240         {
7241                 GL_DepthTest(false);
7242                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7243                 GL_Color(1, 1, 1, 1);
7244                 qglBegin(GL_POLYGON);
7245                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7246                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7247                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7248                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7249                 qglEnd();
7250                 qglBegin(GL_POLYGON);
7251                 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]);
7252                 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]);
7253                 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]);
7254                 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]);
7255                 qglEnd();
7256                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7257         }
7258 #endif
7259
7260         // don't let sound skip if going slow
7261         if (r_refdef.scene.extraupdate)
7262                 S_ExtraUpdate ();
7263
7264         R_ResetViewRendering2D();
7265 }
7266
7267 static const unsigned short bboxelements[36] =
7268 {
7269         5, 1, 3, 5, 3, 7,
7270         6, 2, 0, 6, 0, 4,
7271         7, 3, 2, 7, 2, 6,
7272         4, 0, 1, 4, 1, 5,
7273         4, 5, 7, 4, 7, 6,
7274         1, 0, 2, 1, 2, 3,
7275 };
7276
7277 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7278 {
7279         int i;
7280         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7281
7282         RSurf_ActiveWorldEntity();
7283
7284         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7285         GL_DepthMask(false);
7286         GL_DepthRange(0, 1);
7287         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7288 //      R_Mesh_ResetTextureState();
7289
7290         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7291         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7292         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7293         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7294         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7295         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7296         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7297         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7298         R_FillColors(color4f, 8, cr, cg, cb, ca);
7299         if (r_refdef.fogenabled)
7300         {
7301                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7302                 {
7303                         f1 = RSurf_FogVertex(v);
7304                         f2 = 1 - f1;
7305                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7306                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7307                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7308                 }
7309         }
7310         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7311         R_Mesh_ResetTextureState();
7312         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7313         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7314 }
7315
7316 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7317 {
7318         int i;
7319         float color[4];
7320         prvm_edict_t *edict;
7321         prvm_prog_t *prog_save = prog;
7322
7323         // this function draws bounding boxes of server entities
7324         if (!sv.active)
7325                 return;
7326
7327         GL_CullFace(GL_NONE);
7328         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7329
7330         prog = 0;
7331         SV_VM_Begin();
7332         for (i = 0;i < numsurfaces;i++)
7333         {
7334                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7335                 switch ((int)PRVM_serveredictfloat(edict, solid))
7336                 {
7337                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7338                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7339                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7340                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7341                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7342                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7343                 }
7344                 color[3] *= r_showbboxes.value;
7345                 color[3] = bound(0, color[3], 1);
7346                 GL_DepthTest(!r_showdisabledepthtest.integer);
7347                 GL_CullFace(r_refdef.view.cullface_front);
7348                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7349         }
7350         SV_VM_End();
7351         prog = prog_save;
7352 }
7353
7354 static void R_DrawEntityBBoxes(void)
7355 {
7356         int i;
7357         prvm_edict_t *edict;
7358         vec3_t center;
7359         prvm_prog_t *prog_save = prog;
7360
7361         // this function draws bounding boxes of server entities
7362         if (!sv.active)
7363                 return;
7364
7365         prog = 0;
7366         SV_VM_Begin();
7367         for (i = 0;i < prog->num_edicts;i++)
7368         {
7369                 edict = PRVM_EDICT_NUM(i);
7370                 if (edict->priv.server->free)
7371                         continue;
7372                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7373                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7374                         continue;
7375                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7376                         continue;
7377                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7378                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7379         }
7380         SV_VM_End();
7381         prog = prog_save;
7382 }
7383
7384 static const int nomodelelement3i[24] =
7385 {
7386         5, 2, 0,
7387         5, 1, 2,
7388         5, 0, 3,
7389         5, 3, 1,
7390         0, 2, 4,
7391         2, 1, 4,
7392         3, 0, 4,
7393         1, 3, 4
7394 };
7395
7396 static const unsigned short nomodelelement3s[24] =
7397 {
7398         5, 2, 0,
7399         5, 1, 2,
7400         5, 0, 3,
7401         5, 3, 1,
7402         0, 2, 4,
7403         2, 1, 4,
7404         3, 0, 4,
7405         1, 3, 4
7406 };
7407
7408 static const float nomodelvertex3f[6*3] =
7409 {
7410         -16,   0,   0,
7411          16,   0,   0,
7412           0, -16,   0,
7413           0,  16,   0,
7414           0,   0, -16,
7415           0,   0,  16
7416 };
7417
7418 static const float nomodelcolor4f[6*4] =
7419 {
7420         0.0f, 0.0f, 0.5f, 1.0f,
7421         0.0f, 0.0f, 0.5f, 1.0f,
7422         0.0f, 0.5f, 0.0f, 1.0f,
7423         0.0f, 0.5f, 0.0f, 1.0f,
7424         0.5f, 0.0f, 0.0f, 1.0f,
7425         0.5f, 0.0f, 0.0f, 1.0f
7426 };
7427
7428 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7429 {
7430         int i;
7431         float f1, f2, *c;
7432         float color4f[6*4];
7433
7434         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);
7435
7436         // this is only called once per entity so numsurfaces is always 1, and
7437         // surfacelist is always {0}, so this code does not handle batches
7438
7439         if (rsurface.ent_flags & RENDER_ADDITIVE)
7440         {
7441                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7442                 GL_DepthMask(false);
7443         }
7444         else if (rsurface.colormod[3] < 1)
7445         {
7446                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7447                 GL_DepthMask(false);
7448         }
7449         else
7450         {
7451                 GL_BlendFunc(GL_ONE, GL_ZERO);
7452                 GL_DepthMask(true);
7453         }
7454         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7455         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7456         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7457         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7458         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7459         for (i = 0, c = color4f;i < 6;i++, c += 4)
7460         {
7461                 c[0] *= rsurface.colormod[0];
7462                 c[1] *= rsurface.colormod[1];
7463                 c[2] *= rsurface.colormod[2];
7464                 c[3] *= rsurface.colormod[3];
7465         }
7466         if (r_refdef.fogenabled)
7467         {
7468                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7469                 {
7470                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7471                         f2 = 1 - f1;
7472                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7473                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7474                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7475                 }
7476         }
7477 //      R_Mesh_ResetTextureState();
7478         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7479         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7480         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7481 }
7482
7483 void R_DrawNoModel(entity_render_t *ent)
7484 {
7485         vec3_t org;
7486         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7487         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7488                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7489         else
7490                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7491 }
7492
7493 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7494 {
7495         vec3_t right1, right2, diff, normal;
7496
7497         VectorSubtract (org2, org1, normal);
7498
7499         // calculate 'right' vector for start
7500         VectorSubtract (r_refdef.view.origin, org1, diff);
7501         CrossProduct (normal, diff, right1);
7502         VectorNormalize (right1);
7503
7504         // calculate 'right' vector for end
7505         VectorSubtract (r_refdef.view.origin, org2, diff);
7506         CrossProduct (normal, diff, right2);
7507         VectorNormalize (right2);
7508
7509         vert[ 0] = org1[0] + width * right1[0];
7510         vert[ 1] = org1[1] + width * right1[1];
7511         vert[ 2] = org1[2] + width * right1[2];
7512         vert[ 3] = org1[0] - width * right1[0];
7513         vert[ 4] = org1[1] - width * right1[1];
7514         vert[ 5] = org1[2] - width * right1[2];
7515         vert[ 6] = org2[0] - width * right2[0];
7516         vert[ 7] = org2[1] - width * right2[1];
7517         vert[ 8] = org2[2] - width * right2[2];
7518         vert[ 9] = org2[0] + width * right2[0];
7519         vert[10] = org2[1] + width * right2[1];
7520         vert[11] = org2[2] + width * right2[2];
7521 }
7522
7523 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)
7524 {
7525         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7526         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7527         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7528         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7529         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7530         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7531         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7532         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7533         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7534         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7535         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7536         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7537 }
7538
7539 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7540 {
7541         int i;
7542         float *vertex3f;
7543         float v[3];
7544         VectorSet(v, x, y, z);
7545         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7546                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7547                         break;
7548         if (i == mesh->numvertices)
7549         {
7550                 if (mesh->numvertices < mesh->maxvertices)
7551                 {
7552                         VectorCopy(v, vertex3f);
7553                         mesh->numvertices++;
7554                 }
7555                 return mesh->numvertices;
7556         }
7557         else
7558                 return i;
7559 }
7560
7561 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7562 {
7563         int i;
7564         int *e, element[3];
7565         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7566         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7567         e = mesh->element3i + mesh->numtriangles * 3;
7568         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7569         {
7570                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7571                 if (mesh->numtriangles < mesh->maxtriangles)
7572                 {
7573                         *e++ = element[0];
7574                         *e++ = element[1];
7575                         *e++ = element[2];
7576                         mesh->numtriangles++;
7577                 }
7578                 element[1] = element[2];
7579         }
7580 }
7581
7582 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7583 {
7584         int i;
7585         int *e, element[3];
7586         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7587         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7588         e = mesh->element3i + mesh->numtriangles * 3;
7589         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7590         {
7591                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7592                 if (mesh->numtriangles < mesh->maxtriangles)
7593                 {
7594                         *e++ = element[0];
7595                         *e++ = element[1];
7596                         *e++ = element[2];
7597                         mesh->numtriangles++;
7598                 }
7599                 element[1] = element[2];
7600         }
7601 }
7602
7603 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7604 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7605 {
7606         int planenum, planenum2;
7607         int w;
7608         int tempnumpoints;
7609         mplane_t *plane, *plane2;
7610         double maxdist;
7611         double temppoints[2][256*3];
7612         // figure out how large a bounding box we need to properly compute this brush
7613         maxdist = 0;
7614         for (w = 0;w < numplanes;w++)
7615                 maxdist = max(maxdist, fabs(planes[w].dist));
7616         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7617         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7618         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7619         {
7620                 w = 0;
7621                 tempnumpoints = 4;
7622                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7623                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7624                 {
7625                         if (planenum2 == planenum)
7626                                 continue;
7627                         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);
7628                         w = !w;
7629                 }
7630                 if (tempnumpoints < 3)
7631                         continue;
7632                 // generate elements forming a triangle fan for this polygon
7633                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7634         }
7635 }
7636
7637 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)
7638 {
7639         texturelayer_t *layer;
7640         layer = t->currentlayers + t->currentnumlayers++;
7641         layer->type = type;
7642         layer->depthmask = depthmask;
7643         layer->blendfunc1 = blendfunc1;
7644         layer->blendfunc2 = blendfunc2;
7645         layer->texture = texture;
7646         layer->texmatrix = *matrix;
7647         layer->color[0] = r;
7648         layer->color[1] = g;
7649         layer->color[2] = b;
7650         layer->color[3] = a;
7651 }
7652
7653 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7654 {
7655         if(parms[0] == 0 && parms[1] == 0)
7656                 return false;
7657         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7658                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7659                         return false;
7660         return true;
7661 }
7662
7663 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7664 {
7665         double index, f;
7666         index = parms[2] + rsurface.shadertime * parms[3];
7667         index -= floor(index);
7668         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7669         {
7670         default:
7671         case Q3WAVEFUNC_NONE:
7672         case Q3WAVEFUNC_NOISE:
7673         case Q3WAVEFUNC_COUNT:
7674                 f = 0;
7675                 break;
7676         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7677         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7678         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7679         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7680         case Q3WAVEFUNC_TRIANGLE:
7681                 index *= 4;
7682                 f = index - floor(index);
7683                 if (index < 1)
7684                 {
7685                         // f = f;
7686                 }
7687                 else if (index < 2)
7688                         f = 1 - f;
7689                 else if (index < 3)
7690                         f = -f;
7691                 else
7692                         f = -(1 - f);
7693                 break;
7694         }
7695         f = parms[0] + parms[1] * f;
7696         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7697                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7698         return (float) f;
7699 }
7700
7701 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7702 {
7703         int w, h, idx;
7704         double f;
7705         double offsetd[2];
7706         float tcmat[12];
7707         matrix4x4_t matrix, temp;
7708         switch(tcmod->tcmod)
7709         {
7710                 case Q3TCMOD_COUNT:
7711                 case Q3TCMOD_NONE:
7712                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7713                                 matrix = r_waterscrollmatrix;
7714                         else
7715                                 matrix = identitymatrix;
7716                         break;
7717                 case Q3TCMOD_ENTITYTRANSLATE:
7718                         // this is used in Q3 to allow the gamecode to control texcoord
7719                         // scrolling on the entity, which is not supported in darkplaces yet.
7720                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7721                         break;
7722                 case Q3TCMOD_ROTATE:
7723                         f = tcmod->parms[0] * rsurface.shadertime;
7724                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7725                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7726                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7727                         break;
7728                 case Q3TCMOD_SCALE:
7729                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7730                         break;
7731                 case Q3TCMOD_SCROLL:
7732                         // extra care is needed because of precision breakdown with large values of time
7733                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7734                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7735                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7736                         break;
7737                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7738                         w = (int) tcmod->parms[0];
7739                         h = (int) tcmod->parms[1];
7740                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7741                         f = f - floor(f);
7742                         idx = (int) floor(f * w * h);
7743                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7744                         break;
7745                 case Q3TCMOD_STRETCH:
7746                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7747                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7748                         break;
7749                 case Q3TCMOD_TRANSFORM:
7750                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7751                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7752                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7753                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7754                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7755                         break;
7756                 case Q3TCMOD_TURBULENT:
7757                         // this is handled in the RSurf_PrepareVertices function
7758                         matrix = identitymatrix;
7759                         break;
7760         }
7761         temp = *texmatrix;
7762         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7763 }
7764
7765 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7766 {
7767         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7768         char name[MAX_QPATH];
7769         skinframe_t *skinframe;
7770         unsigned char pixels[296*194];
7771         strlcpy(cache->name, skinname, sizeof(cache->name));
7772         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7773         if (developer_loading.integer)
7774                 Con_Printf("loading %s\n", name);
7775         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7776         if (!skinframe || !skinframe->base)
7777         {
7778                 unsigned char *f;
7779                 fs_offset_t filesize;
7780                 skinframe = NULL;
7781                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7782                 if (f)
7783                 {
7784                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7785                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7786                         Mem_Free(f);
7787                 }
7788         }
7789         cache->skinframe = skinframe;
7790 }
7791
7792 texture_t *R_GetCurrentTexture(texture_t *t)
7793 {
7794         int i;
7795         const entity_render_t *ent = rsurface.entity;
7796         dp_model_t *model = ent->model;
7797         q3shaderinfo_layer_tcmod_t *tcmod;
7798
7799         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7800                 return t->currentframe;
7801         t->update_lastrenderframe = r_textureframe;
7802         t->update_lastrenderentity = (void *)ent;
7803
7804         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7805                 t->camera_entity = ent->entitynumber;
7806         else
7807                 t->camera_entity = 0;
7808
7809         // switch to an alternate material if this is a q1bsp animated material
7810         {
7811                 texture_t *texture = t;
7812                 int s = rsurface.ent_skinnum;
7813                 if ((unsigned int)s >= (unsigned int)model->numskins)
7814                         s = 0;
7815                 if (model->skinscenes)
7816                 {
7817                         if (model->skinscenes[s].framecount > 1)
7818                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7819                         else
7820                                 s = model->skinscenes[s].firstframe;
7821                 }
7822                 if (s > 0)
7823                         t = t + s * model->num_surfaces;
7824                 if (t->animated)
7825                 {
7826                         // use an alternate animation if the entity's frame is not 0,
7827                         // and only if the texture has an alternate animation
7828                         if (rsurface.ent_alttextures && t->anim_total[1])
7829                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7830                         else
7831                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7832                 }
7833                 texture->currentframe = t;
7834         }
7835
7836         // update currentskinframe to be a qw skin or animation frame
7837         if (rsurface.ent_qwskin >= 0)
7838         {
7839                 i = rsurface.ent_qwskin;
7840                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7841                 {
7842                         r_qwskincache_size = cl.maxclients;
7843                         if (r_qwskincache)
7844                                 Mem_Free(r_qwskincache);
7845                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7846                 }
7847                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7848                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7849                 t->currentskinframe = r_qwskincache[i].skinframe;
7850                 if (t->currentskinframe == NULL)
7851                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7852         }
7853         else if (t->numskinframes >= 2)
7854                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7855         if (t->backgroundnumskinframes >= 2)
7856                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7857
7858         t->currentmaterialflags = t->basematerialflags;
7859         t->currentalpha = rsurface.colormod[3];
7860         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7861                 t->currentalpha *= r_wateralpha.value;
7862         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7863                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7864         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7865                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7866         if (!(rsurface.ent_flags & RENDER_LIGHT))
7867                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7868         else if (FAKELIGHT_ENABLED)
7869         {
7870                 // no modellight if using fakelight for the map
7871         }
7872         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7873         {
7874                 // pick a model lighting mode
7875                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7876                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7877                 else
7878                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7879         }
7880         if (rsurface.ent_flags & RENDER_ADDITIVE)
7881                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7882         else if (t->currentalpha < 1)
7883                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7884         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7885         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7886                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7887         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7888                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7889         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7890                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7891         if (t->backgroundnumskinframes)
7892                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7893         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7894         {
7895                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7896                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7897         }
7898         else
7899                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7900         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7901         {
7902                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7903                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7904         }
7905         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7906                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7907
7908         // there is no tcmod
7909         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7910         {
7911                 t->currenttexmatrix = r_waterscrollmatrix;
7912                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7913         }
7914         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7915         {
7916                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7917                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7918         }
7919
7920         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7921                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7922         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7923                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7924
7925         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7926         if (t->currentskinframe->qpixels)
7927                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7928         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7929         if (!t->basetexture)
7930                 t->basetexture = r_texture_notexture;
7931         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7932         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7933         t->nmaptexture = t->currentskinframe->nmap;
7934         if (!t->nmaptexture)
7935                 t->nmaptexture = r_texture_blanknormalmap;
7936         t->glosstexture = r_texture_black;
7937         t->glowtexture = t->currentskinframe->glow;
7938         t->fogtexture = t->currentskinframe->fog;
7939         t->reflectmasktexture = t->currentskinframe->reflect;
7940         if (t->backgroundnumskinframes)
7941         {
7942                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7943                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7944                 t->backgroundglosstexture = r_texture_black;
7945                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7946                 if (!t->backgroundnmaptexture)
7947                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7948         }
7949         else
7950         {
7951                 t->backgroundbasetexture = r_texture_white;
7952                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7953                 t->backgroundglosstexture = r_texture_black;
7954                 t->backgroundglowtexture = NULL;
7955         }
7956         t->specularpower = r_shadow_glossexponent.value;
7957         // TODO: store reference values for these in the texture?
7958         t->specularscale = 0;
7959         if (r_shadow_gloss.integer > 0)
7960         {
7961                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7962                 {
7963                         if (r_shadow_glossintensity.value > 0)
7964                         {
7965                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7966                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7967                                 t->specularscale = r_shadow_glossintensity.value;
7968                         }
7969                 }
7970                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7971                 {
7972                         t->glosstexture = r_texture_white;
7973                         t->backgroundglosstexture = r_texture_white;
7974                         t->specularscale = r_shadow_gloss2intensity.value;
7975                         t->specularpower = r_shadow_gloss2exponent.value;
7976                 }
7977         }
7978         t->specularscale *= t->specularscalemod;
7979         t->specularpower *= t->specularpowermod;
7980         t->rtlightambient = 0;
7981
7982         // lightmaps mode looks bad with dlights using actual texturing, so turn
7983         // off the colormap and glossmap, but leave the normalmap on as it still
7984         // accurately represents the shading involved
7985         if (gl_lightmaps.integer)
7986         {
7987                 t->basetexture = r_texture_grey128;
7988                 t->pantstexture = r_texture_black;
7989                 t->shirttexture = r_texture_black;
7990                 t->nmaptexture = r_texture_blanknormalmap;
7991                 t->glosstexture = r_texture_black;
7992                 t->glowtexture = NULL;
7993                 t->fogtexture = NULL;
7994                 t->reflectmasktexture = NULL;
7995                 t->backgroundbasetexture = NULL;
7996                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7997                 t->backgroundglosstexture = r_texture_black;
7998                 t->backgroundglowtexture = NULL;
7999                 t->specularscale = 0;
8000                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8001         }
8002
8003         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8004         VectorClear(t->dlightcolor);
8005         t->currentnumlayers = 0;
8006         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8007         {
8008                 int blendfunc1, blendfunc2;
8009                 qboolean depthmask;
8010                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8011                 {
8012                         blendfunc1 = GL_SRC_ALPHA;
8013                         blendfunc2 = GL_ONE;
8014                 }
8015                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8016                 {
8017                         blendfunc1 = GL_SRC_ALPHA;
8018                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8019                 }
8020                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8021                 {
8022                         blendfunc1 = t->customblendfunc[0];
8023                         blendfunc2 = t->customblendfunc[1];
8024                 }
8025                 else
8026                 {
8027                         blendfunc1 = GL_ONE;
8028                         blendfunc2 = GL_ZERO;
8029                 }
8030                 // don't colormod evilblend textures
8031                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8032                         VectorSet(t->lightmapcolor, 1, 1, 1);
8033                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8034                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8035                 {
8036                         // fullbright is not affected by r_refdef.lightmapintensity
8037                         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]);
8038                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8039                                 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]);
8040                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8041                                 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]);
8042                 }
8043                 else
8044                 {
8045                         vec3_t ambientcolor;
8046                         float colorscale;
8047                         // set the color tint used for lights affecting this surface
8048                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8049                         colorscale = 2;
8050                         // q3bsp has no lightmap updates, so the lightstylevalue that
8051                         // would normally be baked into the lightmap must be
8052                         // applied to the color
8053                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8054                         if (model->type == mod_brushq3)
8055                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8056                         colorscale *= r_refdef.lightmapintensity;
8057                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8058                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8059                         // basic lit geometry
8060                         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]);
8061                         // add pants/shirt if needed
8062                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8063                                 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]);
8064                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8065                                 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]);
8066                         // now add ambient passes if needed
8067                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8068                         {
8069                                 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]);
8070                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8071                                         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]);
8072                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8073                                         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]);
8074                         }
8075                 }
8076                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8077                         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]);
8078                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8079                 {
8080                         // if this is opaque use alpha blend which will darken the earlier
8081                         // passes cheaply.
8082                         //
8083                         // if this is an alpha blended material, all the earlier passes
8084                         // were darkened by fog already, so we only need to add the fog
8085                         // color ontop through the fog mask texture
8086                         //
8087                         // if this is an additive blended material, all the earlier passes
8088                         // were darkened by fog already, and we should not add fog color
8089                         // (because the background was not darkened, there is no fog color
8090                         // that was lost behind it).
8091                         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]);
8092                 }
8093         }
8094
8095         return t->currentframe;
8096 }
8097
8098 rsurfacestate_t rsurface;
8099
8100 void RSurf_ActiveWorldEntity(void)
8101 {
8102         dp_model_t *model = r_refdef.scene.worldmodel;
8103         //if (rsurface.entity == r_refdef.scene.worldentity)
8104         //      return;
8105         rsurface.entity = r_refdef.scene.worldentity;
8106         rsurface.skeleton = NULL;
8107         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8108         rsurface.ent_skinnum = 0;
8109         rsurface.ent_qwskin = -1;
8110         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8111         rsurface.shadertime = r_refdef.scene.time;
8112         rsurface.matrix = identitymatrix;
8113         rsurface.inversematrix = identitymatrix;
8114         rsurface.matrixscale = 1;
8115         rsurface.inversematrixscale = 1;
8116         R_EntityMatrix(&identitymatrix);
8117         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8118         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8119         rsurface.fograngerecip = r_refdef.fograngerecip;
8120         rsurface.fogheightfade = r_refdef.fogheightfade;
8121         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8122         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8123         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8124         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8125         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8126         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8127         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8128         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8129         rsurface.colormod[3] = 1;
8130         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);
8131         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8132         rsurface.frameblend[0].lerp = 1;
8133         rsurface.ent_alttextures = false;
8134         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8135         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8136         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8137         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8139         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8140         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8141         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8142         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8143         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8144         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8145         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8146         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8147         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8148         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8149         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8150         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8151         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8152         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8153         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8154         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8155         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8156         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8157         rsurface.modelelement3i = model->surfmesh.data_element3i;
8158         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8159         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8160         rsurface.modelelement3s = model->surfmesh.data_element3s;
8161         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8162         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8163         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8164         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8165         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8166         rsurface.modelsurfaces = model->data_surfaces;
8167         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8168         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8169         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8170         rsurface.modelgeneratedvertex = false;
8171         rsurface.batchgeneratedvertex = false;
8172         rsurface.batchfirstvertex = 0;
8173         rsurface.batchnumvertices = 0;
8174         rsurface.batchfirsttriangle = 0;
8175         rsurface.batchnumtriangles = 0;
8176         rsurface.batchvertex3f  = NULL;
8177         rsurface.batchvertex3f_vertexbuffer = NULL;
8178         rsurface.batchvertex3f_bufferoffset = 0;
8179         rsurface.batchsvector3f = NULL;
8180         rsurface.batchsvector3f_vertexbuffer = NULL;
8181         rsurface.batchsvector3f_bufferoffset = 0;
8182         rsurface.batchtvector3f = NULL;
8183         rsurface.batchtvector3f_vertexbuffer = NULL;
8184         rsurface.batchtvector3f_bufferoffset = 0;
8185         rsurface.batchnormal3f  = NULL;
8186         rsurface.batchnormal3f_vertexbuffer = NULL;
8187         rsurface.batchnormal3f_bufferoffset = 0;
8188         rsurface.batchlightmapcolor4f = NULL;
8189         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8190         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8191         rsurface.batchtexcoordtexture2f = NULL;
8192         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8193         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8194         rsurface.batchtexcoordlightmap2f = NULL;
8195         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8196         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8197         rsurface.batchvertexmesh = NULL;
8198         rsurface.batchvertexmeshbuffer = NULL;
8199         rsurface.batchvertex3fbuffer = NULL;
8200         rsurface.batchelement3i = NULL;
8201         rsurface.batchelement3i_indexbuffer = NULL;
8202         rsurface.batchelement3i_bufferoffset = 0;
8203         rsurface.batchelement3s = NULL;
8204         rsurface.batchelement3s_indexbuffer = NULL;
8205         rsurface.batchelement3s_bufferoffset = 0;
8206         rsurface.passcolor4f = NULL;
8207         rsurface.passcolor4f_vertexbuffer = NULL;
8208         rsurface.passcolor4f_bufferoffset = 0;
8209 }
8210
8211 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8212 {
8213         dp_model_t *model = ent->model;
8214         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8215         //      return;
8216         rsurface.entity = (entity_render_t *)ent;
8217         rsurface.skeleton = ent->skeleton;
8218         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8219         rsurface.ent_skinnum = ent->skinnum;
8220         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;
8221         rsurface.ent_flags = ent->flags;
8222         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8223         rsurface.matrix = ent->matrix;
8224         rsurface.inversematrix = ent->inversematrix;
8225         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8226         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8227         R_EntityMatrix(&rsurface.matrix);
8228         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8229         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8230         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8231         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8232         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8233         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8234         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8235         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8236         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8237         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8238         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8239         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8240         rsurface.colormod[3] = ent->alpha;
8241         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8242         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8243         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8244         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8245         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8246         if (ent->model->brush.submodel && !prepass)
8247         {
8248                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8249                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8250         }
8251         if (model->surfmesh.isanimated && model->AnimateVertices)
8252         {
8253                 if (ent->animcache_vertex3f)
8254                 {
8255                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8256                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8257                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8258                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8259                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8260                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8261                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8262                 }
8263                 else if (wanttangents)
8264                 {
8265                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8266                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8267                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8268                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8269                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8270                         rsurface.modelvertexmesh = NULL;
8271                         rsurface.modelvertexmeshbuffer = NULL;
8272                         rsurface.modelvertex3fbuffer = NULL;
8273                 }
8274                 else if (wantnormals)
8275                 {
8276                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8277                         rsurface.modelsvector3f = NULL;
8278                         rsurface.modeltvector3f = NULL;
8279                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8280                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8281                         rsurface.modelvertexmesh = NULL;
8282                         rsurface.modelvertexmeshbuffer = NULL;
8283                         rsurface.modelvertex3fbuffer = NULL;
8284                 }
8285                 else
8286                 {
8287                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8288                         rsurface.modelsvector3f = NULL;
8289                         rsurface.modeltvector3f = NULL;
8290                         rsurface.modelnormal3f = NULL;
8291                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8292                         rsurface.modelvertexmesh = NULL;
8293                         rsurface.modelvertexmeshbuffer = NULL;
8294                         rsurface.modelvertex3fbuffer = NULL;
8295                 }
8296                 rsurface.modelvertex3f_vertexbuffer = 0;
8297                 rsurface.modelvertex3f_bufferoffset = 0;
8298                 rsurface.modelsvector3f_vertexbuffer = 0;
8299                 rsurface.modelsvector3f_bufferoffset = 0;
8300                 rsurface.modeltvector3f_vertexbuffer = 0;
8301                 rsurface.modeltvector3f_bufferoffset = 0;
8302                 rsurface.modelnormal3f_vertexbuffer = 0;
8303                 rsurface.modelnormal3f_bufferoffset = 0;
8304                 rsurface.modelgeneratedvertex = true;
8305         }
8306         else
8307         {
8308                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8309                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8310                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8311                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8312                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8313                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8314                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8315                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8316                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8317                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8318                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8319                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8320                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8321                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8322                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8323                 rsurface.modelgeneratedvertex = false;
8324         }
8325         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8326         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8327         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8328         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8329         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8330         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8331         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8332         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8333         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8334         rsurface.modelelement3i = model->surfmesh.data_element3i;
8335         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8336         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8337         rsurface.modelelement3s = model->surfmesh.data_element3s;
8338         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8339         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8340         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8341         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8342         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8343         rsurface.modelsurfaces = model->data_surfaces;
8344         rsurface.batchgeneratedvertex = false;
8345         rsurface.batchfirstvertex = 0;
8346         rsurface.batchnumvertices = 0;
8347         rsurface.batchfirsttriangle = 0;
8348         rsurface.batchnumtriangles = 0;
8349         rsurface.batchvertex3f  = NULL;
8350         rsurface.batchvertex3f_vertexbuffer = NULL;
8351         rsurface.batchvertex3f_bufferoffset = 0;
8352         rsurface.batchsvector3f = NULL;
8353         rsurface.batchsvector3f_vertexbuffer = NULL;
8354         rsurface.batchsvector3f_bufferoffset = 0;
8355         rsurface.batchtvector3f = NULL;
8356         rsurface.batchtvector3f_vertexbuffer = NULL;
8357         rsurface.batchtvector3f_bufferoffset = 0;
8358         rsurface.batchnormal3f  = NULL;
8359         rsurface.batchnormal3f_vertexbuffer = NULL;
8360         rsurface.batchnormal3f_bufferoffset = 0;
8361         rsurface.batchlightmapcolor4f = NULL;
8362         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8363         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8364         rsurface.batchtexcoordtexture2f = NULL;
8365         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8366         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8367         rsurface.batchtexcoordlightmap2f = NULL;
8368         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8369         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8370         rsurface.batchvertexmesh = NULL;
8371         rsurface.batchvertexmeshbuffer = NULL;
8372         rsurface.batchvertex3fbuffer = NULL;
8373         rsurface.batchelement3i = NULL;
8374         rsurface.batchelement3i_indexbuffer = NULL;
8375         rsurface.batchelement3i_bufferoffset = 0;
8376         rsurface.batchelement3s = NULL;
8377         rsurface.batchelement3s_indexbuffer = NULL;
8378         rsurface.batchelement3s_bufferoffset = 0;
8379         rsurface.passcolor4f = NULL;
8380         rsurface.passcolor4f_vertexbuffer = NULL;
8381         rsurface.passcolor4f_bufferoffset = 0;
8382 }
8383
8384 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)
8385 {
8386         rsurface.entity = r_refdef.scene.worldentity;
8387         rsurface.skeleton = NULL;
8388         rsurface.ent_skinnum = 0;
8389         rsurface.ent_qwskin = -1;
8390         rsurface.ent_flags = entflags;
8391         rsurface.shadertime = r_refdef.scene.time - shadertime;
8392         rsurface.modelnumvertices = numvertices;
8393         rsurface.modelnumtriangles = numtriangles;
8394         rsurface.matrix = *matrix;
8395         rsurface.inversematrix = *inversematrix;
8396         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8397         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8398         R_EntityMatrix(&rsurface.matrix);
8399         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8400         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8401         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8402         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8403         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8404         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8405         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8406         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8407         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8408         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8409         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8410         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8411         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);
8412         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8413         rsurface.frameblend[0].lerp = 1;
8414         rsurface.ent_alttextures = false;
8415         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8416         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8417         if (wanttangents)
8418         {
8419                 rsurface.modelvertex3f = (float *)vertex3f;
8420                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8421                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8422                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8423         }
8424         else if (wantnormals)
8425         {
8426                 rsurface.modelvertex3f = (float *)vertex3f;
8427                 rsurface.modelsvector3f = NULL;
8428                 rsurface.modeltvector3f = NULL;
8429                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8430         }
8431         else
8432         {
8433                 rsurface.modelvertex3f = (float *)vertex3f;
8434                 rsurface.modelsvector3f = NULL;
8435                 rsurface.modeltvector3f = NULL;
8436                 rsurface.modelnormal3f = NULL;
8437         }
8438         rsurface.modelvertexmesh = NULL;
8439         rsurface.modelvertexmeshbuffer = NULL;
8440         rsurface.modelvertex3fbuffer = NULL;
8441         rsurface.modelvertex3f_vertexbuffer = 0;
8442         rsurface.modelvertex3f_bufferoffset = 0;
8443         rsurface.modelsvector3f_vertexbuffer = 0;
8444         rsurface.modelsvector3f_bufferoffset = 0;
8445         rsurface.modeltvector3f_vertexbuffer = 0;
8446         rsurface.modeltvector3f_bufferoffset = 0;
8447         rsurface.modelnormal3f_vertexbuffer = 0;
8448         rsurface.modelnormal3f_bufferoffset = 0;
8449         rsurface.modelgeneratedvertex = true;
8450         rsurface.modellightmapcolor4f  = (float *)color4f;
8451         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8452         rsurface.modellightmapcolor4f_bufferoffset = 0;
8453         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8454         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8455         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8456         rsurface.modeltexcoordlightmap2f  = NULL;
8457         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8458         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8459         rsurface.modelelement3i = (int *)element3i;
8460         rsurface.modelelement3i_indexbuffer = NULL;
8461         rsurface.modelelement3i_bufferoffset = 0;
8462         rsurface.modelelement3s = (unsigned short *)element3s;
8463         rsurface.modelelement3s_indexbuffer = NULL;
8464         rsurface.modelelement3s_bufferoffset = 0;
8465         rsurface.modellightmapoffsets = NULL;
8466         rsurface.modelsurfaces = NULL;
8467         rsurface.batchgeneratedvertex = false;
8468         rsurface.batchfirstvertex = 0;
8469         rsurface.batchnumvertices = 0;
8470         rsurface.batchfirsttriangle = 0;
8471         rsurface.batchnumtriangles = 0;
8472         rsurface.batchvertex3f  = NULL;
8473         rsurface.batchvertex3f_vertexbuffer = NULL;
8474         rsurface.batchvertex3f_bufferoffset = 0;
8475         rsurface.batchsvector3f = NULL;
8476         rsurface.batchsvector3f_vertexbuffer = NULL;
8477         rsurface.batchsvector3f_bufferoffset = 0;
8478         rsurface.batchtvector3f = NULL;
8479         rsurface.batchtvector3f_vertexbuffer = NULL;
8480         rsurface.batchtvector3f_bufferoffset = 0;
8481         rsurface.batchnormal3f  = NULL;
8482         rsurface.batchnormal3f_vertexbuffer = NULL;
8483         rsurface.batchnormal3f_bufferoffset = 0;
8484         rsurface.batchlightmapcolor4f = NULL;
8485         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8486         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8487         rsurface.batchtexcoordtexture2f = NULL;
8488         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8489         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8490         rsurface.batchtexcoordlightmap2f = NULL;
8491         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8492         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8493         rsurface.batchvertexmesh = NULL;
8494         rsurface.batchvertexmeshbuffer = NULL;
8495         rsurface.batchvertex3fbuffer = NULL;
8496         rsurface.batchelement3i = NULL;
8497         rsurface.batchelement3i_indexbuffer = NULL;
8498         rsurface.batchelement3i_bufferoffset = 0;
8499         rsurface.batchelement3s = NULL;
8500         rsurface.batchelement3s_indexbuffer = NULL;
8501         rsurface.batchelement3s_bufferoffset = 0;
8502         rsurface.passcolor4f = NULL;
8503         rsurface.passcolor4f_vertexbuffer = NULL;
8504         rsurface.passcolor4f_bufferoffset = 0;
8505
8506         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8507         {
8508                 if ((wantnormals || wanttangents) && !normal3f)
8509                 {
8510                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8511                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8512                 }
8513                 if (wanttangents && !svector3f)
8514                 {
8515                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8516                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8517                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8518                 }
8519         }
8520 }
8521
8522 float RSurf_FogPoint(const float *v)
8523 {
8524         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8525         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8526         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8527         float FogHeightFade = r_refdef.fogheightfade;
8528         float fogfrac;
8529         unsigned int fogmasktableindex;
8530         if (r_refdef.fogplaneviewabove)
8531                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8532         else
8533                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8534         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8535         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8536 }
8537
8538 float RSurf_FogVertex(const float *v)
8539 {
8540         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8541         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8542         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8543         float FogHeightFade = rsurface.fogheightfade;
8544         float fogfrac;
8545         unsigned int fogmasktableindex;
8546         if (r_refdef.fogplaneviewabove)
8547                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8548         else
8549                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8550         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8551         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8552 }
8553
8554 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8555 {
8556         int i;
8557         for (i = 0;i < numelements;i++)
8558                 outelement3i[i] = inelement3i[i] + adjust;
8559 }
8560
8561 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8562 extern cvar_t gl_vbo;
8563 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8564 {
8565         int deformindex;
8566         int firsttriangle;
8567         int numtriangles;
8568         int firstvertex;
8569         int endvertex;
8570         int numvertices;
8571         int surfacefirsttriangle;
8572         int surfacenumtriangles;
8573         int surfacefirstvertex;
8574         int surfaceendvertex;
8575         int surfacenumvertices;
8576         int batchnumvertices;
8577         int batchnumtriangles;
8578         int needsupdate;
8579         int i, j;
8580         qboolean gaps;
8581         qboolean dynamicvertex;
8582         float amplitude;
8583         float animpos;
8584         float scale;
8585         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8586         float waveparms[4];
8587         q3shaderinfo_deform_t *deform;
8588         const msurface_t *surface, *firstsurface;
8589         r_vertexmesh_t *vertexmesh;
8590         if (!texturenumsurfaces)
8591                 return;
8592         // find vertex range of this surface batch
8593         gaps = false;
8594         firstsurface = texturesurfacelist[0];
8595         firsttriangle = firstsurface->num_firsttriangle;
8596         batchnumvertices = 0;
8597         batchnumtriangles = 0;
8598         firstvertex = endvertex = firstsurface->num_firstvertex;
8599         for (i = 0;i < texturenumsurfaces;i++)
8600         {
8601                 surface = texturesurfacelist[i];
8602                 if (surface != firstsurface + i)
8603                         gaps = true;
8604                 surfacefirstvertex = surface->num_firstvertex;
8605                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8606                 surfacenumvertices = surface->num_vertices;
8607                 surfacenumtriangles = surface->num_triangles;
8608                 if (firstvertex > surfacefirstvertex)
8609                         firstvertex = surfacefirstvertex;
8610                 if (endvertex < surfaceendvertex)
8611                         endvertex = surfaceendvertex;
8612                 batchnumvertices += surfacenumvertices;
8613                 batchnumtriangles += surfacenumtriangles;
8614         }
8615
8616         // we now know the vertex range used, and if there are any gaps in it
8617         rsurface.batchfirstvertex = firstvertex;
8618         rsurface.batchnumvertices = endvertex - firstvertex;
8619         rsurface.batchfirsttriangle = firsttriangle;
8620         rsurface.batchnumtriangles = batchnumtriangles;
8621
8622         // this variable holds flags for which properties have been updated that
8623         // may require regenerating vertexmesh array...
8624         needsupdate = 0;
8625
8626         // check if any dynamic vertex processing must occur
8627         dynamicvertex = false;
8628
8629         // if there is a chance of animated vertex colors, it's a dynamic batch
8630         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8631         {
8632                 dynamicvertex = true;
8633                 batchneed |= BATCHNEED_NOGAPS;
8634                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8635         }
8636
8637         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8638         {
8639                 switch (deform->deform)
8640                 {
8641                 default:
8642                 case Q3DEFORM_PROJECTIONSHADOW:
8643                 case Q3DEFORM_TEXT0:
8644                 case Q3DEFORM_TEXT1:
8645                 case Q3DEFORM_TEXT2:
8646                 case Q3DEFORM_TEXT3:
8647                 case Q3DEFORM_TEXT4:
8648                 case Q3DEFORM_TEXT5:
8649                 case Q3DEFORM_TEXT6:
8650                 case Q3DEFORM_TEXT7:
8651                 case Q3DEFORM_NONE:
8652                         break;
8653                 case Q3DEFORM_AUTOSPRITE:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_AUTOSPRITE2:
8659                         dynamicvertex = true;
8660                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8661                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8662                         break;
8663                 case Q3DEFORM_NORMAL:
8664                         dynamicvertex = true;
8665                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8666                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8667                         break;
8668                 case Q3DEFORM_WAVE:
8669                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8670                                 break; // if wavefunc is a nop, ignore this transform
8671                         dynamicvertex = true;
8672                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8673                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8674                         break;
8675                 case Q3DEFORM_BULGE:
8676                         dynamicvertex = true;
8677                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8678                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8679                         break;
8680                 case Q3DEFORM_MOVE:
8681                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8682                                 break; // if wavefunc is a nop, ignore this transform
8683                         dynamicvertex = true;
8684                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8685                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8686                         break;
8687                 }
8688         }
8689         switch(rsurface.texture->tcgen.tcgen)
8690         {
8691         default:
8692         case Q3TCGEN_TEXTURE:
8693                 break;
8694         case Q3TCGEN_LIGHTMAP:
8695                 dynamicvertex = true;
8696                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8697                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8698                 break;
8699         case Q3TCGEN_VECTOR:
8700                 dynamicvertex = true;
8701                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8702                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8703                 break;
8704         case Q3TCGEN_ENVIRONMENT:
8705                 dynamicvertex = true;
8706                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8707                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8708                 break;
8709         }
8710         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8711         {
8712                 dynamicvertex = true;
8713                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8714                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8715         }
8716
8717         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8718         {
8719                 dynamicvertex = true;
8720                 batchneed |= BATCHNEED_NOGAPS;
8721                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8722         }
8723
8724         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8725         {
8726                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8727                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8728                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8729                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8730                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8731                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8732                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8733         }
8734
8735         // when the model data has no vertex buffer (dynamic mesh), we need to
8736         // eliminate gaps
8737         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8738                 batchneed |= BATCHNEED_NOGAPS;
8739
8740         // if needsupdate, we have to do a dynamic vertex batch for sure
8741         if (needsupdate & batchneed)
8742                 dynamicvertex = true;
8743
8744         // see if we need to build vertexmesh from arrays
8745         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8746                 dynamicvertex = true;
8747
8748         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8749         // also some drivers strongly dislike firstvertex
8750         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8751                 dynamicvertex = true;
8752
8753         rsurface.batchvertex3f = rsurface.modelvertex3f;
8754         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8755         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8756         rsurface.batchsvector3f = rsurface.modelsvector3f;
8757         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8758         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8759         rsurface.batchtvector3f = rsurface.modeltvector3f;
8760         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8761         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8762         rsurface.batchnormal3f = rsurface.modelnormal3f;
8763         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8764         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8765         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8766         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8767         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8768         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8769         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8770         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8771         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8772         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8773         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8774         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8775         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8776         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8777         rsurface.batchelement3i = rsurface.modelelement3i;
8778         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8779         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8780         rsurface.batchelement3s = rsurface.modelelement3s;
8781         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8782         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8783
8784         // if any dynamic vertex processing has to occur in software, we copy the
8785         // entire surface list together before processing to rebase the vertices
8786         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8787         //
8788         // if any gaps exist and we do not have a static vertex buffer, we have to
8789         // copy the surface list together to avoid wasting upload bandwidth on the
8790         // vertices in the gaps.
8791         //
8792         // if gaps exist and we have a static vertex buffer, we still have to
8793         // combine the index buffer ranges into one dynamic index buffer.
8794         //
8795         // in all cases we end up with data that can be drawn in one call.
8796
8797         if (!dynamicvertex)
8798         {
8799                 // static vertex data, just set pointers...
8800                 rsurface.batchgeneratedvertex = false;
8801                 // if there are gaps, we want to build a combined index buffer,
8802                 // otherwise use the original static buffer with an appropriate offset
8803                 if (gaps)
8804                 {
8805                         // build a new triangle elements array for this batch
8806                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8807                         rsurface.batchfirsttriangle = 0;
8808                         numtriangles = 0;
8809                         for (i = 0;i < texturenumsurfaces;i++)
8810                         {
8811                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8812                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8813                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8814                                 numtriangles += surfacenumtriangles;
8815                         }
8816                         rsurface.batchelement3i_indexbuffer = NULL;
8817                         rsurface.batchelement3i_bufferoffset = 0;
8818                         rsurface.batchelement3s = NULL;
8819                         rsurface.batchelement3s_indexbuffer = NULL;
8820                         rsurface.batchelement3s_bufferoffset = 0;
8821                         if (endvertex <= 65536)
8822                         {
8823                                 // make a 16bit (unsigned short) index array if possible
8824                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8825                                 for (i = 0;i < numtriangles*3;i++)
8826                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8827                         }
8828                 }
8829                 return;
8830         }
8831
8832         // something needs software processing, do it for real...
8833         // we only directly handle separate array data in this case and then
8834         // generate interleaved data if needed...
8835         rsurface.batchgeneratedvertex = true;
8836
8837         // now copy the vertex data into a combined array and make an index array
8838         // (this is what Quake3 does all the time)
8839         //if (gaps || rsurface.batchfirstvertex)
8840         {
8841                 rsurface.batchvertex3fbuffer = NULL;
8842                 rsurface.batchvertexmesh = NULL;
8843                 rsurface.batchvertexmeshbuffer = NULL;
8844                 rsurface.batchvertex3f = NULL;
8845                 rsurface.batchvertex3f_vertexbuffer = NULL;
8846                 rsurface.batchvertex3f_bufferoffset = 0;
8847                 rsurface.batchsvector3f = NULL;
8848                 rsurface.batchsvector3f_vertexbuffer = NULL;
8849                 rsurface.batchsvector3f_bufferoffset = 0;
8850                 rsurface.batchtvector3f = NULL;
8851                 rsurface.batchtvector3f_vertexbuffer = NULL;
8852                 rsurface.batchtvector3f_bufferoffset = 0;
8853                 rsurface.batchnormal3f = NULL;
8854                 rsurface.batchnormal3f_vertexbuffer = NULL;
8855                 rsurface.batchnormal3f_bufferoffset = 0;
8856                 rsurface.batchlightmapcolor4f = NULL;
8857                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8858                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8859                 rsurface.batchtexcoordtexture2f = NULL;
8860                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8861                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8862                 rsurface.batchtexcoordlightmap2f = NULL;
8863                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8864                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8865                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8866                 rsurface.batchelement3i_indexbuffer = NULL;
8867                 rsurface.batchelement3i_bufferoffset = 0;
8868                 rsurface.batchelement3s = NULL;
8869                 rsurface.batchelement3s_indexbuffer = NULL;
8870                 rsurface.batchelement3s_bufferoffset = 0;
8871                 // we'll only be setting up certain arrays as needed
8872                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8873                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8874                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8875                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8876                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8877                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8878                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8879                 {
8880                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8881                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8882                 }
8883                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8884                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8885                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8886                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8887                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8888                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8889                 numvertices = 0;
8890                 numtriangles = 0;
8891                 for (i = 0;i < texturenumsurfaces;i++)
8892                 {
8893                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8894                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8895                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8896                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8897                         // copy only the data requested
8898                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8899                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8900                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8901                         {
8902                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8903                                 {
8904                                         if (rsurface.batchvertex3f)
8905                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8906                                         else
8907                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8908                                 }
8909                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8910                                 {
8911                                         if (rsurface.modelnormal3f)
8912                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8913                                         else
8914                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8915                                 }
8916                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8917                                 {
8918                                         if (rsurface.modelsvector3f)
8919                                         {
8920                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8921                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8922                                         }
8923                                         else
8924                                         {
8925                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8926                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8927                                         }
8928                                 }
8929                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8930                                 {
8931                                         if (rsurface.modellightmapcolor4f)
8932                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8933                                         else
8934                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8935                                 }
8936                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8937                                 {
8938                                         if (rsurface.modeltexcoordtexture2f)
8939                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8940                                         else
8941                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8942                                 }
8943                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8944                                 {
8945                                         if (rsurface.modeltexcoordlightmap2f)
8946                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8947                                         else
8948                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8949                                 }
8950                         }
8951                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8952                         numvertices += surfacenumvertices;
8953                         numtriangles += surfacenumtriangles;
8954                 }
8955
8956                 // generate a 16bit index array as well if possible
8957                 // (in general, dynamic batches fit)
8958                 if (numvertices <= 65536)
8959                 {
8960                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8961                         for (i = 0;i < numtriangles*3;i++)
8962                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8963                 }
8964
8965                 // since we've copied everything, the batch now starts at 0
8966                 rsurface.batchfirstvertex = 0;
8967                 rsurface.batchnumvertices = batchnumvertices;
8968                 rsurface.batchfirsttriangle = 0;
8969                 rsurface.batchnumtriangles = batchnumtriangles;
8970         }
8971
8972         // q1bsp surfaces rendered in vertex color mode have to have colors
8973         // calculated based on lightstyles
8974         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8975         {
8976                 // generate color arrays for the surfaces in this list
8977                 int c[4];
8978                 int scale;
8979                 int size3;
8980                 const int *offsets;
8981                 const unsigned char *lm;
8982                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8983                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8984                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8985                 numvertices = 0;
8986                 for (i = 0;i < texturenumsurfaces;i++)
8987                 {
8988                         surface = texturesurfacelist[i];
8989                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8990                         surfacenumvertices = surface->num_vertices;
8991                         if (surface->lightmapinfo->samples)
8992                         {
8993                                 for (j = 0;j < surfacenumvertices;j++)
8994                                 {
8995                                         lm = surface->lightmapinfo->samples + offsets[j];
8996                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8997                                         VectorScale(lm, scale, c);
8998                                         if (surface->lightmapinfo->styles[1] != 255)
8999                                         {
9000                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9001                                                 lm += size3;
9002                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9003                                                 VectorMA(c, scale, lm, c);
9004                                                 if (surface->lightmapinfo->styles[2] != 255)
9005                                                 {
9006                                                         lm += size3;
9007                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9008                                                         VectorMA(c, scale, lm, c);
9009                                                         if (surface->lightmapinfo->styles[3] != 255)
9010                                                         {
9011                                                                 lm += size3;
9012                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9013                                                                 VectorMA(c, scale, lm, c);
9014                                                         }
9015                                                 }
9016                                         }
9017                                         c[0] >>= 7;
9018                                         c[1] >>= 7;
9019                                         c[2] >>= 7;
9020                                         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);
9021                                         numvertices++;
9022                                 }
9023                         }
9024                         else
9025                         {
9026                                 for (j = 0;j < surfacenumvertices;j++)
9027                                 {
9028                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9029                                         numvertices++;
9030                                 }
9031                         }
9032                 }
9033         }
9034
9035         // if vertices are deformed (sprite flares and things in maps, possibly
9036         // water waves, bulges and other deformations), modify the copied vertices
9037         // in place
9038         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9039         {
9040                 switch (deform->deform)
9041                 {
9042                 default:
9043                 case Q3DEFORM_PROJECTIONSHADOW:
9044                 case Q3DEFORM_TEXT0:
9045                 case Q3DEFORM_TEXT1:
9046                 case Q3DEFORM_TEXT2:
9047                 case Q3DEFORM_TEXT3:
9048                 case Q3DEFORM_TEXT4:
9049                 case Q3DEFORM_TEXT5:
9050                 case Q3DEFORM_TEXT6:
9051                 case Q3DEFORM_TEXT7:
9052                 case Q3DEFORM_NONE:
9053                         break;
9054                 case Q3DEFORM_AUTOSPRITE:
9055                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9056                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9057                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9058                         VectorNormalize(newforward);
9059                         VectorNormalize(newright);
9060                         VectorNormalize(newup);
9061 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9062 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9063 //                      rsurface.batchvertex3f_bufferoffset = 0;
9064 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9065 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9066 //                      rsurface.batchsvector3f_bufferoffset = 0;
9067 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9068 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9069 //                      rsurface.batchtvector3f_bufferoffset = 0;
9070 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9071 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9072 //                      rsurface.batchnormal3f_bufferoffset = 0;
9073                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9074                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9075                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9076                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9077                                 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);
9078                         // a single autosprite surface can contain multiple sprites...
9079                         for (j = 0;j < batchnumvertices - 3;j += 4)
9080                         {
9081                                 VectorClear(center);
9082                                 for (i = 0;i < 4;i++)
9083                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9084                                 VectorScale(center, 0.25f, center);
9085                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9086                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9087                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9088                                 for (i = 0;i < 4;i++)
9089                                 {
9090                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9091                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9092                                 }
9093                         }
9094                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9095                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9096                         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);
9097                         break;
9098                 case Q3DEFORM_AUTOSPRITE2:
9099                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9100                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9101                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9102                         VectorNormalize(newforward);
9103                         VectorNormalize(newright);
9104                         VectorNormalize(newup);
9105 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9106 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9107 //                      rsurface.batchvertex3f_bufferoffset = 0;
9108                         {
9109                                 const float *v1, *v2;
9110                                 vec3_t start, end;
9111                                 float f, l;
9112                                 struct
9113                                 {
9114                                         float length2;
9115                                         const float *v1;
9116                                         const float *v2;
9117                                 }
9118                                 shortest[2];
9119                                 memset(shortest, 0, sizeof(shortest));
9120                                 // a single autosprite surface can contain multiple sprites...
9121                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9122                                 {
9123                                         VectorClear(center);
9124                                         for (i = 0;i < 4;i++)
9125                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9126                                         VectorScale(center, 0.25f, center);
9127                                         // find the two shortest edges, then use them to define the
9128                                         // axis vectors for rotating around the central axis
9129                                         for (i = 0;i < 6;i++)
9130                                         {
9131                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9132                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9133                                                 l = VectorDistance2(v1, v2);
9134                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9135                                                 if (v1[2] != v2[2])
9136                                                         l += (1.0f / 1024.0f);
9137                                                 if (shortest[0].length2 > l || i == 0)
9138                                                 {
9139                                                         shortest[1] = shortest[0];
9140                                                         shortest[0].length2 = l;
9141                                                         shortest[0].v1 = v1;
9142                                                         shortest[0].v2 = v2;
9143                                                 }
9144                                                 else if (shortest[1].length2 > l || i == 1)
9145                                                 {
9146                                                         shortest[1].length2 = l;
9147                                                         shortest[1].v1 = v1;
9148                                                         shortest[1].v2 = v2;
9149                                                 }
9150                                         }
9151                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9152                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9153                                         // this calculates the right vector from the shortest edge
9154                                         // and the up vector from the edge midpoints
9155                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9156                                         VectorNormalize(right);
9157                                         VectorSubtract(end, start, up);
9158                                         VectorNormalize(up);
9159                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9160                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9161                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9162                                         VectorNegate(forward, forward);
9163                                         VectorReflect(forward, 0, up, forward);
9164                                         VectorNormalize(forward);
9165                                         CrossProduct(up, forward, newright);
9166                                         VectorNormalize(newright);
9167                                         // rotate the quad around the up axis vector, this is made
9168                                         // especially easy by the fact we know the quad is flat,
9169                                         // so we only have to subtract the center position and
9170                                         // measure distance along the right vector, and then
9171                                         // multiply that by the newright vector and add back the
9172                                         // center position
9173                                         // we also need to subtract the old position to undo the
9174                                         // displacement from the center, which we do with a
9175                                         // DotProduct, the subtraction/addition of center is also
9176                                         // optimized into DotProducts here
9177                                         l = DotProduct(right, center);
9178                                         for (i = 0;i < 4;i++)
9179                                         {
9180                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9181                                                 f = DotProduct(right, v1) - l;
9182                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9183                                         }
9184                                 }
9185                         }
9186                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9187                         {
9188 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9190 //                              rsurface.batchnormal3f_bufferoffset = 0;
9191                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9192                         }
9193                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9194                         {
9195 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9196 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9197 //                              rsurface.batchsvector3f_bufferoffset = 0;
9198 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9199 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9200 //                              rsurface.batchtvector3f_bufferoffset = 0;
9201                                 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);
9202                         }
9203                         break;
9204                 case Q3DEFORM_NORMAL:
9205                         // deform the normals to make reflections wavey
9206                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9207                         rsurface.batchnormal3f_vertexbuffer = NULL;
9208                         rsurface.batchnormal3f_bufferoffset = 0;
9209                         for (j = 0;j < batchnumvertices;j++)
9210                         {
9211                                 float vertex[3];
9212                                 float *normal = rsurface.batchnormal3f + 3*j;
9213                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9214                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9215                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9216                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9217                                 VectorNormalize(normal);
9218                         }
9219                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9220                         {
9221 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9222 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9223 //                              rsurface.batchsvector3f_bufferoffset = 0;
9224 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9225 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9226 //                              rsurface.batchtvector3f_bufferoffset = 0;
9227                                 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);
9228                         }
9229                         break;
9230                 case Q3DEFORM_WAVE:
9231                         // deform vertex array to make wavey water and flags and such
9232                         waveparms[0] = deform->waveparms[0];
9233                         waveparms[1] = deform->waveparms[1];
9234                         waveparms[2] = deform->waveparms[2];
9235                         waveparms[3] = deform->waveparms[3];
9236                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9237                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9238                         // this is how a divisor of vertex influence on deformation
9239                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9240                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9241 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9242 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9243 //                      rsurface.batchvertex3f_bufferoffset = 0;
9244 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9245 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9246 //                      rsurface.batchnormal3f_bufferoffset = 0;
9247                         for (j = 0;j < batchnumvertices;j++)
9248                         {
9249                                 // if the wavefunc depends on time, evaluate it per-vertex
9250                                 if (waveparms[3])
9251                                 {
9252                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9253                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9254                                 }
9255                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9256                         }
9257                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9258                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9259                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9260                         {
9261 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9262 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9263 //                              rsurface.batchsvector3f_bufferoffset = 0;
9264 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9265 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9266 //                              rsurface.batchtvector3f_bufferoffset = 0;
9267                                 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);
9268                         }
9269                         break;
9270                 case Q3DEFORM_BULGE:
9271                         // deform vertex array to make the surface have moving bulges
9272 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9273 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9274 //                      rsurface.batchvertex3f_bufferoffset = 0;
9275 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9276 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9277 //                      rsurface.batchnormal3f_bufferoffset = 0;
9278                         for (j = 0;j < batchnumvertices;j++)
9279                         {
9280                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9281                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9282                         }
9283                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9284                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9285                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9286                         {
9287 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9288 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9289 //                              rsurface.batchsvector3f_bufferoffset = 0;
9290 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9291 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9292 //                              rsurface.batchtvector3f_bufferoffset = 0;
9293                                 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);
9294                         }
9295                         break;
9296                 case Q3DEFORM_MOVE:
9297                         // deform vertex array
9298                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9299                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9300                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9301                         VectorScale(deform->parms, scale, waveparms);
9302 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9303 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9304 //                      rsurface.batchvertex3f_bufferoffset = 0;
9305                         for (j = 0;j < batchnumvertices;j++)
9306                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9307                         break;
9308                 }
9309         }
9310
9311         // generate texcoords based on the chosen texcoord source
9312         switch(rsurface.texture->tcgen.tcgen)
9313         {
9314         default:
9315         case Q3TCGEN_TEXTURE:
9316                 break;
9317         case Q3TCGEN_LIGHTMAP:
9318 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9319 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9320 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9321                 if (rsurface.batchtexcoordlightmap2f)
9322                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9323                 break;
9324         case Q3TCGEN_VECTOR:
9325 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9326 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9327 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9328                 for (j = 0;j < batchnumvertices;j++)
9329                 {
9330                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9331                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9332                 }
9333                 break;
9334         case Q3TCGEN_ENVIRONMENT:
9335                 // make environment reflections using a spheremap
9336                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9337                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9338                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9339                 for (j = 0;j < batchnumvertices;j++)
9340                 {
9341                         // identical to Q3A's method, but executed in worldspace so
9342                         // carried models can be shiny too
9343
9344                         float viewer[3], d, reflected[3], worldreflected[3];
9345
9346                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9347                         // VectorNormalize(viewer);
9348
9349                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9350
9351                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9352                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9353                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9354                         // note: this is proportinal to viewer, so we can normalize later
9355
9356                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9357                         VectorNormalize(worldreflected);
9358
9359                         // note: this sphere map only uses world x and z!
9360                         // so positive and negative y will LOOK THE SAME.
9361                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9362                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9363                 }
9364                 break;
9365         }
9366         // the only tcmod that needs software vertex processing is turbulent, so
9367         // check for it here and apply the changes if needed
9368         // and we only support that as the first one
9369         // (handling a mixture of turbulent and other tcmods would be problematic
9370         //  without punting it entirely to a software path)
9371         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9372         {
9373                 amplitude = rsurface.texture->tcmods[0].parms[1];
9374                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9375 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9376 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9377 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9378                 for (j = 0;j < batchnumvertices;j++)
9379                 {
9380                         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);
9381                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9382                 }
9383         }
9384
9385         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9386         {
9387                 // convert the modified arrays to vertex structs
9388 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9389 //              rsurface.batchvertexmeshbuffer = NULL;
9390                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9391                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9392                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9393                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9394                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9395                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9396                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9397                 {
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                         {
9400                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9401                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9402                         }
9403                 }
9404                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9405                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9406                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9407                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9408                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9409                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9410                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9411                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9412                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9413         }
9414 }
9415
9416 void RSurf_DrawBatch(void)
9417 {
9418         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9419         // through the pipeline, killing it earlier in the pipeline would have
9420         // per-surface overhead rather than per-batch overhead, so it's best to
9421         // reject it here, before it hits glDraw.
9422         if (rsurface.batchnumtriangles == 0)
9423                 return;
9424 #if 0
9425         // batch debugging code
9426         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9427         {
9428                 int i;
9429                 int j;
9430                 int c;
9431                 const int *e;
9432                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9433                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9434                 {
9435                         c = e[i];
9436                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9437                         {
9438                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9439                                 {
9440                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9441                                                 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);
9442                                         break;
9443                                 }
9444                         }
9445                 }
9446         }
9447 #endif
9448         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);
9449 }
9450
9451 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9452 {
9453         // pick the closest matching water plane
9454         int planeindex, vertexindex, bestplaneindex = -1;
9455         float d, bestd;
9456         vec3_t vert;
9457         const float *v;
9458         r_waterstate_waterplane_t *p;
9459         qboolean prepared = false;
9460         bestd = 0;
9461         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9462         {
9463                 if(p->camera_entity != rsurface.texture->camera_entity)
9464                         continue;
9465                 d = 0;
9466                 if(!prepared)
9467                 {
9468                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9469                         prepared = true;
9470                         if(rsurface.batchnumvertices == 0)
9471                                 break;
9472                 }
9473                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9474                 {
9475                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9476                         d += fabs(PlaneDiff(vert, &p->plane));
9477                 }
9478                 if (bestd > d || bestplaneindex < 0)
9479                 {
9480                         bestd = d;
9481                         bestplaneindex = planeindex;
9482                 }
9483         }
9484         return bestplaneindex;
9485         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9486         // this situation though, as it might be better to render single larger
9487         // batches with useless stuff (backface culled for example) than to
9488         // render multiple smaller batches
9489 }
9490
9491 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9492 {
9493         int i;
9494         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9495         rsurface.passcolor4f_vertexbuffer = 0;
9496         rsurface.passcolor4f_bufferoffset = 0;
9497         for (i = 0;i < rsurface.batchnumvertices;i++)
9498                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9499 }
9500
9501 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9502 {
9503         int i;
9504         float f;
9505         const float *v;
9506         const float *c;
9507         float *c2;
9508         if (rsurface.passcolor4f)
9509         {
9510                 // generate color arrays
9511                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9512                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9513                 rsurface.passcolor4f_vertexbuffer = 0;
9514                 rsurface.passcolor4f_bufferoffset = 0;
9515                 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)
9516                 {
9517                         f = RSurf_FogVertex(v);
9518                         c2[0] = c[0] * f;
9519                         c2[1] = c[1] * f;
9520                         c2[2] = c[2] * f;
9521                         c2[3] = c[3];
9522                 }
9523         }
9524         else
9525         {
9526                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9527                 rsurface.passcolor4f_vertexbuffer = 0;
9528                 rsurface.passcolor4f_bufferoffset = 0;
9529                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9530                 {
9531                         f = RSurf_FogVertex(v);
9532                         c2[0] = f;
9533                         c2[1] = f;
9534                         c2[2] = f;
9535                         c2[3] = 1;
9536                 }
9537         }
9538 }
9539
9540 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9541 {
9542         int i;
9543         float f;
9544         const float *v;
9545         const float *c;
9546         float *c2;
9547         if (!rsurface.passcolor4f)
9548                 return;
9549         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9550         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9551         rsurface.passcolor4f_vertexbuffer = 0;
9552         rsurface.passcolor4f_bufferoffset = 0;
9553         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)
9554         {
9555                 f = RSurf_FogVertex(v);
9556                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9557                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9558                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9559                 c2[3] = c[3];
9560         }
9561 }
9562
9563 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9564 {
9565         int i;
9566         const float *c;
9567         float *c2;
9568         if (!rsurface.passcolor4f)
9569                 return;
9570         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9571         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9572         rsurface.passcolor4f_vertexbuffer = 0;
9573         rsurface.passcolor4f_bufferoffset = 0;
9574         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9575         {
9576                 c2[0] = c[0] * r;
9577                 c2[1] = c[1] * g;
9578                 c2[2] = c[2] * b;
9579                 c2[3] = c[3] * a;
9580         }
9581 }
9582
9583 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9584 {
9585         int i;
9586         const float *c;
9587         float *c2;
9588         if (!rsurface.passcolor4f)
9589                 return;
9590         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9591         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9592         rsurface.passcolor4f_vertexbuffer = 0;
9593         rsurface.passcolor4f_bufferoffset = 0;
9594         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9595         {
9596                 c2[0] = c[0] + r_refdef.scene.ambient;
9597                 c2[1] = c[1] + r_refdef.scene.ambient;
9598                 c2[2] = c[2] + r_refdef.scene.ambient;
9599                 c2[3] = c[3];
9600         }
9601 }
9602
9603 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9604 {
9605         // TODO: optimize
9606         rsurface.passcolor4f = NULL;
9607         rsurface.passcolor4f_vertexbuffer = 0;
9608         rsurface.passcolor4f_bufferoffset = 0;
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         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9614         RSurf_DrawBatch();
9615 }
9616
9617 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9618 {
9619         // TODO: optimize applyfog && applycolor case
9620         // just apply fog if necessary, and tint the fog color array if necessary
9621         rsurface.passcolor4f = NULL;
9622         rsurface.passcolor4f_vertexbuffer = 0;
9623         rsurface.passcolor4f_bufferoffset = 0;
9624         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9625         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9626         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9627         GL_Color(r, g, b, a);
9628         RSurf_DrawBatch();
9629 }
9630
9631 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9632 {
9633         // TODO: optimize
9634         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9635         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9636         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9637         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9638         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9639         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9640         GL_Color(r, g, b, a);
9641         RSurf_DrawBatch();
9642 }
9643
9644 static void RSurf_DrawBatch_GL11_ClampColor(void)
9645 {
9646         int i;
9647         const float *c1;
9648         float *c2;
9649         if (!rsurface.passcolor4f)
9650                 return;
9651         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9652         {
9653                 c2[0] = bound(0.0f, c1[0], 1.0f);
9654                 c2[1] = bound(0.0f, c1[1], 1.0f);
9655                 c2[2] = bound(0.0f, c1[2], 1.0f);
9656                 c2[3] = bound(0.0f, c1[3], 1.0f);
9657         }
9658 }
9659
9660 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9661 {
9662         int i;
9663         float f;
9664         const float *v;
9665         const float *n;
9666         float *c;
9667         //vec3_t eyedir;
9668
9669         // fake shading
9670         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9671         rsurface.passcolor4f_vertexbuffer = 0;
9672         rsurface.passcolor4f_bufferoffset = 0;
9673         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)
9674         {
9675                 f = -DotProduct(r_refdef.view.forward, n);
9676                 f = max(0, f);
9677                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9678                 f *= r_refdef.lightmapintensity;
9679                 Vector4Set(c, f, f, f, 1);
9680         }
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9684 {
9685         RSurf_DrawBatch_GL11_ApplyFakeLight();
9686         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9687         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9688         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9689         GL_Color(r, g, b, a);
9690         RSurf_DrawBatch();
9691 }
9692
9693 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9694 {
9695         int i;
9696         float f;
9697         float alpha;
9698         const float *v;
9699         const float *n;
9700         float *c;
9701         vec3_t ambientcolor;
9702         vec3_t diffusecolor;
9703         vec3_t lightdir;
9704         // TODO: optimize
9705         // model lighting
9706         VectorCopy(rsurface.modellight_lightdir, lightdir);
9707         f = 0.5f * r_refdef.lightmapintensity;
9708         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9709         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9710         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9711         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9712         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9713         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9714         alpha = *a;
9715         if (VectorLength2(diffusecolor) > 0)
9716         {
9717                 // q3-style directional shading
9718                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9719                 rsurface.passcolor4f_vertexbuffer = 0;
9720                 rsurface.passcolor4f_bufferoffset = 0;
9721                 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)
9722                 {
9723                         if ((f = DotProduct(n, lightdir)) > 0)
9724                                 VectorMA(ambientcolor, f, diffusecolor, c);
9725                         else
9726                                 VectorCopy(ambientcolor, c);
9727                         c[3] = alpha;
9728                 }
9729                 *r = 1;
9730                 *g = 1;
9731                 *b = 1;
9732                 *a = 1;
9733                 *applycolor = false;
9734         }
9735         else
9736         {
9737                 *r = ambientcolor[0];
9738                 *g = ambientcolor[1];
9739                 *b = ambientcolor[2];
9740                 rsurface.passcolor4f = NULL;
9741                 rsurface.passcolor4f_vertexbuffer = 0;
9742                 rsurface.passcolor4f_bufferoffset = 0;
9743         }
9744 }
9745
9746 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9747 {
9748         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9749         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9750         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9751         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9752         GL_Color(r, g, b, a);
9753         RSurf_DrawBatch();
9754 }
9755
9756 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9757 {
9758         int i;
9759         float f;
9760         const float *v;
9761         float *c;
9762
9763         // fake shading
9764         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9765         rsurface.passcolor4f_vertexbuffer = 0;
9766         rsurface.passcolor4f_bufferoffset = 0;
9767
9768         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9769         {
9770                 f = 1 - RSurf_FogVertex(v);
9771                 c[0] = r;
9772                 c[1] = g;
9773                 c[2] = b;
9774                 c[3] = f * a;
9775         }
9776 }
9777
9778 void RSurf_SetupDepthAndCulling(void)
9779 {
9780         // submodels are biased to avoid z-fighting with world surfaces that they
9781         // may be exactly overlapping (avoids z-fighting artifacts on certain
9782         // doors and things in Quake maps)
9783         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9784         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9785         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9786         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9787 }
9788
9789 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9790 {
9791         // transparent sky would be ridiculous
9792         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9793                 return;
9794         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9795         skyrenderlater = true;
9796         RSurf_SetupDepthAndCulling();
9797         GL_DepthMask(true);
9798         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9799         // skymasking on them, and Quake3 never did sky masking (unlike
9800         // software Quake and software Quake2), so disable the sky masking
9801         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9802         // and skymasking also looks very bad when noclipping outside the
9803         // level, so don't use it then either.
9804         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9805         {
9806                 R_Mesh_ResetTextureState();
9807                 if (skyrendermasked)
9808                 {
9809                         R_SetupShader_DepthOrShadow(false);
9810                         // depth-only (masking)
9811                         GL_ColorMask(0,0,0,0);
9812                         // just to make sure that braindead drivers don't draw
9813                         // anything despite that colormask...
9814                         GL_BlendFunc(GL_ZERO, GL_ONE);
9815                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9816                         if (rsurface.batchvertex3fbuffer)
9817                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9818                         else
9819                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9820                 }
9821                 else
9822                 {
9823                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9824                         // fog sky
9825                         GL_BlendFunc(GL_ONE, GL_ZERO);
9826                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9827                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9828                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9829                 }
9830                 RSurf_DrawBatch();
9831                 if (skyrendermasked)
9832                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9833         }
9834         R_Mesh_ResetTextureState();
9835         GL_Color(1, 1, 1, 1);
9836 }
9837
9838 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9839 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9840 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9841 {
9842         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9843                 return;
9844         if (prepass)
9845         {
9846                 // render screenspace normalmap to texture
9847                 GL_DepthMask(true);
9848                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9849                 RSurf_DrawBatch();
9850         }
9851
9852         // bind lightmap texture
9853
9854         // water/refraction/reflection/camera surfaces have to be handled specially
9855         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9856         {
9857                 int start, end, startplaneindex;
9858                 for (start = 0;start < texturenumsurfaces;start = end)
9859                 {
9860                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9861                         if(startplaneindex < 0)
9862                         {
9863                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9864                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9865                                 end = start + 1;
9866                                 continue;
9867                         }
9868                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9869                                 ;
9870                         // now that we have a batch using the same planeindex, render it
9871                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9872                         {
9873                                 // render water or distortion background
9874                                 GL_DepthMask(true);
9875                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9876                                 RSurf_DrawBatch();
9877                                 // blend surface on top
9878                                 GL_DepthMask(false);
9879                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9880                                 RSurf_DrawBatch();
9881                         }
9882                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9883                         {
9884                                 // render surface with reflection texture as input
9885                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9886                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9887                                 RSurf_DrawBatch();
9888                         }
9889                 }
9890                 return;
9891         }
9892
9893         // render surface batch normally
9894         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9895         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);
9896         RSurf_DrawBatch();
9897 }
9898
9899 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9900 {
9901         // OpenGL 1.3 path - anything not completely ancient
9902         qboolean applycolor;
9903         qboolean applyfog;
9904         int layerindex;
9905         const texturelayer_t *layer;
9906         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);
9907         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9908
9909         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9910         {
9911                 vec4_t layercolor;
9912                 int layertexrgbscale;
9913                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9914                 {
9915                         if (layerindex == 0)
9916                                 GL_AlphaTest(true);
9917                         else
9918                         {
9919                                 GL_AlphaTest(false);
9920                                 GL_DepthFunc(GL_EQUAL);
9921                         }
9922                 }
9923                 GL_DepthMask(layer->depthmask && writedepth);
9924                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9925                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9926                 {
9927                         layertexrgbscale = 4;
9928                         VectorScale(layer->color, 0.25f, layercolor);
9929                 }
9930                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9931                 {
9932                         layertexrgbscale = 2;
9933                         VectorScale(layer->color, 0.5f, layercolor);
9934                 }
9935                 else
9936                 {
9937                         layertexrgbscale = 1;
9938                         VectorScale(layer->color, 1.0f, layercolor);
9939                 }
9940                 layercolor[3] = layer->color[3];
9941                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9942                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9943                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9944                 switch (layer->type)
9945                 {
9946                 case TEXTURELAYERTYPE_LITTEXTURE:
9947                         // single-pass lightmapped texture with 2x rgbscale
9948                         R_Mesh_TexBind(0, r_texture_white);
9949                         R_Mesh_TexMatrix(0, NULL);
9950                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9951                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9952                         R_Mesh_TexBind(1, layer->texture);
9953                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9954                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9955                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9956                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9957                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9958                         else if (FAKELIGHT_ENABLED)
9959                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9960                         else if (rsurface.uselightmaptexture)
9961                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9962                         else
9963                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9964                         break;
9965                 case TEXTURELAYERTYPE_TEXTURE:
9966                         // singletexture unlit texture with transparency support
9967                         R_Mesh_TexBind(0, layer->texture);
9968                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9969                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9970                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9971                         R_Mesh_TexBind(1, 0);
9972                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9973                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9974                         break;
9975                 case TEXTURELAYERTYPE_FOG:
9976                         // singletexture fogging
9977                         if (layer->texture)
9978                         {
9979                                 R_Mesh_TexBind(0, layer->texture);
9980                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9983                         }
9984                         else
9985                         {
9986                                 R_Mesh_TexBind(0, 0);
9987                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9988                         }
9989                         R_Mesh_TexBind(1, 0);
9990                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9991                         // generate a color array for the fog pass
9992                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9993                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9994                         RSurf_DrawBatch();
9995                         break;
9996                 default:
9997                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9998                 }
9999         }
10000         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10001         {
10002                 GL_DepthFunc(GL_LEQUAL);
10003                 GL_AlphaTest(false);
10004         }
10005 }
10006
10007 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10008 {
10009         // OpenGL 1.1 - crusty old voodoo path
10010         qboolean applyfog;
10011         int layerindex;
10012         const texturelayer_t *layer;
10013         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);
10014         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10015
10016         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10017         {
10018                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10019                 {
10020                         if (layerindex == 0)
10021                                 GL_AlphaTest(true);
10022                         else
10023                         {
10024                                 GL_AlphaTest(false);
10025                                 GL_DepthFunc(GL_EQUAL);
10026                         }
10027                 }
10028                 GL_DepthMask(layer->depthmask && writedepth);
10029                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10030                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10031                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10032                 switch (layer->type)
10033                 {
10034                 case TEXTURELAYERTYPE_LITTEXTURE:
10035                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10036                         {
10037                                 // two-pass lit texture with 2x rgbscale
10038                                 // first the lightmap pass
10039                                 R_Mesh_TexBind(0, r_texture_white);
10040                                 R_Mesh_TexMatrix(0, NULL);
10041                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10042                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10043                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10044                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10045                                 else if (FAKELIGHT_ENABLED)
10046                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10047                                 else if (rsurface.uselightmaptexture)
10048                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10049                                 else
10050                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10051                                 // then apply the texture to it
10052                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10053                                 R_Mesh_TexBind(0, layer->texture);
10054                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                                 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);
10058                         }
10059                         else
10060                         {
10061                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10062                                 R_Mesh_TexBind(0, layer->texture);
10063                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10064                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10065                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10066                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10067                                         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);
10068                                 else
10069                                         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);
10070                         }
10071                         break;
10072                 case TEXTURELAYERTYPE_TEXTURE:
10073                         // singletexture unlit texture with transparency support
10074                         R_Mesh_TexBind(0, layer->texture);
10075                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10076                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10077                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10078                         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);
10079                         break;
10080                 case TEXTURELAYERTYPE_FOG:
10081                         // singletexture fogging
10082                         if (layer->texture)
10083                         {
10084                                 R_Mesh_TexBind(0, layer->texture);
10085                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10086                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10087                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10088                         }
10089                         else
10090                         {
10091                                 R_Mesh_TexBind(0, 0);
10092                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10093                         }
10094                         // generate a color array for the fog pass
10095                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10096                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10097                         RSurf_DrawBatch();
10098                         break;
10099                 default:
10100                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10101                 }
10102         }
10103         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10104         {
10105                 GL_DepthFunc(GL_LEQUAL);
10106                 GL_AlphaTest(false);
10107         }
10108 }
10109
10110 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10111 {
10112         int vi;
10113         int j;
10114         r_vertexgeneric_t *batchvertex;
10115         float c[4];
10116
10117 //      R_Mesh_ResetTextureState();
10118         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10119
10120         if(rsurface.texture && rsurface.texture->currentskinframe)
10121         {
10122                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10123                 c[3] *= rsurface.texture->currentalpha;
10124         }
10125         else
10126         {
10127                 c[0] = 1;
10128                 c[1] = 0;
10129                 c[2] = 1;
10130                 c[3] = 1;
10131         }
10132
10133         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10134         {
10135                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10136                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10137                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10138         }
10139
10140         // brighten it up (as texture value 127 means "unlit")
10141         c[0] *= 2 * r_refdef.view.colorscale;
10142         c[1] *= 2 * r_refdef.view.colorscale;
10143         c[2] *= 2 * r_refdef.view.colorscale;
10144
10145         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10146                 c[3] *= r_wateralpha.value;
10147
10148         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10149         {
10150                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10151                 GL_DepthMask(false);
10152         }
10153         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10154         {
10155                 GL_BlendFunc(GL_ONE, GL_ONE);
10156                 GL_DepthMask(false);
10157         }
10158         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10159         {
10160                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10161                 GL_DepthMask(false);
10162         }
10163         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10164         {
10165                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10166                 GL_DepthMask(false);
10167         }
10168         else
10169         {
10170                 GL_BlendFunc(GL_ONE, GL_ZERO);
10171                 GL_DepthMask(writedepth);
10172         }
10173
10174         if (r_showsurfaces.integer == 3)
10175         {
10176                 rsurface.passcolor4f = NULL;
10177
10178                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10179                 {
10180                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10181
10182                         rsurface.passcolor4f = NULL;
10183                         rsurface.passcolor4f_vertexbuffer = 0;
10184                         rsurface.passcolor4f_bufferoffset = 0;
10185                 }
10186                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10187                 {
10188                         qboolean applycolor = true;
10189                         float one = 1.0;
10190
10191                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10192
10193                         r_refdef.lightmapintensity = 1;
10194                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10195                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10196                 }
10197                 else if (FAKELIGHT_ENABLED)
10198                 {
10199                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10200
10201                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10202                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10203                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10204                 }
10205                 else
10206                 {
10207                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10208
10209                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10210                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10211                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10212                 }
10213
10214                 if(!rsurface.passcolor4f)
10215                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10216
10217                 RSurf_DrawBatch_GL11_ApplyAmbient();
10218                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10219                 if(r_refdef.fogenabled)
10220                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10221                 RSurf_DrawBatch_GL11_ClampColor();
10222
10223                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10224                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10225                 RSurf_DrawBatch();
10226         }
10227         else if (!r_refdef.view.showdebug)
10228         {
10229                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10230                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10231                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10232                 {
10233                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10234                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10235                 }
10236                 R_Mesh_PrepareVertices_Generic_Unlock();
10237                 RSurf_DrawBatch();
10238         }
10239         else if (r_showsurfaces.integer == 4)
10240         {
10241                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10242                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10243                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10244                 {
10245                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10246                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10247                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10248                 }
10249                 R_Mesh_PrepareVertices_Generic_Unlock();
10250                 RSurf_DrawBatch();
10251         }
10252         else if (r_showsurfaces.integer == 2)
10253         {
10254                 const int *e;
10255                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10256                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10257                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10258                 {
10259                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10260                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10261                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10262                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10263                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10264                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10265                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10266                 }
10267                 R_Mesh_PrepareVertices_Generic_Unlock();
10268                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10269         }
10270         else
10271         {
10272                 int texturesurfaceindex;
10273                 int k;
10274                 const msurface_t *surface;
10275                 float surfacecolor4f[4];
10276                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10277                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10278                 vi = 0;
10279                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10280                 {
10281                         surface = texturesurfacelist[texturesurfaceindex];
10282                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10283                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10284                         for (j = 0;j < surface->num_vertices;j++)
10285                         {
10286                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10287                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10288                                 vi++;
10289                         }
10290                 }
10291                 R_Mesh_PrepareVertices_Generic_Unlock();
10292                 RSurf_DrawBatch();
10293         }
10294 }
10295
10296 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10297 {
10298         CHECKGLERROR
10299         RSurf_SetupDepthAndCulling();
10300         if (r_showsurfaces.integer)
10301         {
10302                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10303                 return;
10304         }
10305         switch (vid.renderpath)
10306         {
10307         case RENDERPATH_GL20:
10308         case RENDERPATH_D3D9:
10309         case RENDERPATH_D3D10:
10310         case RENDERPATH_D3D11:
10311         case RENDERPATH_SOFT:
10312         case RENDERPATH_GLES2:
10313                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10314                 break;
10315         case RENDERPATH_GL13:
10316         case RENDERPATH_GLES1:
10317                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10318                 break;
10319         case RENDERPATH_GL11:
10320                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10321                 break;
10322         }
10323         CHECKGLERROR
10324 }
10325
10326 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10327 {
10328         CHECKGLERROR
10329         RSurf_SetupDepthAndCulling();
10330         if (r_showsurfaces.integer)
10331         {
10332                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10333                 return;
10334         }
10335         switch (vid.renderpath)
10336         {
10337         case RENDERPATH_GL20:
10338         case RENDERPATH_D3D9:
10339         case RENDERPATH_D3D10:
10340         case RENDERPATH_D3D11:
10341         case RENDERPATH_SOFT:
10342         case RENDERPATH_GLES2:
10343                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10344                 break;
10345         case RENDERPATH_GL13:
10346         case RENDERPATH_GLES1:
10347                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10348                 break;
10349         case RENDERPATH_GL11:
10350                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10351                 break;
10352         }
10353         CHECKGLERROR
10354 }
10355
10356 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10357 {
10358         int i, j;
10359         int texturenumsurfaces, endsurface;
10360         texture_t *texture;
10361         const msurface_t *surface;
10362         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10363
10364         // if the model is static it doesn't matter what value we give for
10365         // wantnormals and wanttangents, so this logic uses only rules applicable
10366         // to a model, knowing that they are meaningless otherwise
10367         if (ent == r_refdef.scene.worldentity)
10368                 RSurf_ActiveWorldEntity();
10369         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10370                 RSurf_ActiveModelEntity(ent, false, false, false);
10371         else
10372         {
10373                 switch (vid.renderpath)
10374                 {
10375                 case RENDERPATH_GL20:
10376                 case RENDERPATH_D3D9:
10377                 case RENDERPATH_D3D10:
10378                 case RENDERPATH_D3D11:
10379                 case RENDERPATH_SOFT:
10380                 case RENDERPATH_GLES2:
10381                         RSurf_ActiveModelEntity(ent, true, true, false);
10382                         break;
10383                 case RENDERPATH_GL11:
10384                 case RENDERPATH_GL13:
10385                 case RENDERPATH_GLES1:
10386                         RSurf_ActiveModelEntity(ent, true, false, false);
10387                         break;
10388                 }
10389         }
10390
10391         if (r_transparentdepthmasking.integer)
10392         {
10393                 qboolean setup = false;
10394                 for (i = 0;i < numsurfaces;i = j)
10395                 {
10396                         j = i + 1;
10397                         surface = rsurface.modelsurfaces + surfacelist[i];
10398                         texture = surface->texture;
10399                         rsurface.texture = R_GetCurrentTexture(texture);
10400                         rsurface.lightmaptexture = NULL;
10401                         rsurface.deluxemaptexture = NULL;
10402                         rsurface.uselightmaptexture = false;
10403                         // scan ahead until we find a different texture
10404                         endsurface = min(i + 1024, numsurfaces);
10405                         texturenumsurfaces = 0;
10406                         texturesurfacelist[texturenumsurfaces++] = surface;
10407                         for (;j < endsurface;j++)
10408                         {
10409                                 surface = rsurface.modelsurfaces + surfacelist[j];
10410                                 if (texture != surface->texture)
10411                                         break;
10412                                 texturesurfacelist[texturenumsurfaces++] = surface;
10413                         }
10414                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10415                                 continue;
10416                         // render the range of surfaces as depth
10417                         if (!setup)
10418                         {
10419                                 setup = true;
10420                                 GL_ColorMask(0,0,0,0);
10421                                 GL_Color(1,1,1,1);
10422                                 GL_DepthTest(true);
10423                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10424                                 GL_DepthMask(true);
10425 //                              R_Mesh_ResetTextureState();
10426                                 R_SetupShader_DepthOrShadow(false);
10427                         }
10428                         RSurf_SetupDepthAndCulling();
10429                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10430                         if (rsurface.batchvertex3fbuffer)
10431                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10432                         else
10433                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10434                         RSurf_DrawBatch();
10435                 }
10436                 if (setup)
10437                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10438         }
10439
10440         for (i = 0;i < numsurfaces;i = j)
10441         {
10442                 j = i + 1;
10443                 surface = rsurface.modelsurfaces + surfacelist[i];
10444                 texture = surface->texture;
10445                 rsurface.texture = R_GetCurrentTexture(texture);
10446                 // scan ahead until we find a different texture
10447                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10448                 texturenumsurfaces = 0;
10449                 texturesurfacelist[texturenumsurfaces++] = surface;
10450                 if(FAKELIGHT_ENABLED)
10451                 {
10452                         rsurface.lightmaptexture = NULL;
10453                         rsurface.deluxemaptexture = NULL;
10454                         rsurface.uselightmaptexture = false;
10455                         for (;j < endsurface;j++)
10456                         {
10457                                 surface = rsurface.modelsurfaces + surfacelist[j];
10458                                 if (texture != surface->texture)
10459                                         break;
10460                                 texturesurfacelist[texturenumsurfaces++] = surface;
10461                         }
10462                 }
10463                 else
10464                 {
10465                         rsurface.lightmaptexture = surface->lightmaptexture;
10466                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10467                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10468                         for (;j < endsurface;j++)
10469                         {
10470                                 surface = rsurface.modelsurfaces + surfacelist[j];
10471                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10472                                         break;
10473                                 texturesurfacelist[texturenumsurfaces++] = surface;
10474                         }
10475                 }
10476                 // render the range of surfaces
10477                 if (ent == r_refdef.scene.worldentity)
10478                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10479                 else
10480                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10481         }
10482         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10483 }
10484
10485 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10486 {
10487         // transparent surfaces get pushed off into the transparent queue
10488         int surfacelistindex;
10489         const msurface_t *surface;
10490         vec3_t tempcenter, center;
10491         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10492         {
10493                 surface = texturesurfacelist[surfacelistindex];
10494                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10495                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10496                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10497                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10498                 if (queueentity->transparent_offset) // transparent offset
10499                 {
10500                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10501                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10502                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10503                 }
10504                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10505         }
10506 }
10507
10508 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10509 {
10510         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10511                 return;
10512         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10513                 return;
10514         RSurf_SetupDepthAndCulling();
10515         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10516         if (rsurface.batchvertex3fbuffer)
10517                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10518         else
10519                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10520         RSurf_DrawBatch();
10521 }
10522
10523 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10524 {
10525         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10526         CHECKGLERROR
10527         if (depthonly)
10528                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10529         else if (prepass)
10530         {
10531                 if (!rsurface.texture->currentnumlayers)
10532                         return;
10533                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10534                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10535                 else
10536                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10537         }
10538         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10539                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10540         else if (!rsurface.texture->currentnumlayers)
10541                 return;
10542         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10543         {
10544                 // in the deferred case, transparent surfaces were queued during prepass
10545                 if (!r_shadow_usingdeferredprepass)
10546                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10547         }
10548         else
10549         {
10550                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10551                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10552         }
10553         CHECKGLERROR
10554 }
10555
10556 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10557 {
10558         int i, j;
10559         texture_t *texture;
10560         R_FrameData_SetMark();
10561         // break the surface list down into batches by texture and use of lightmapping
10562         for (i = 0;i < numsurfaces;i = j)
10563         {
10564                 j = i + 1;
10565                 // texture is the base texture pointer, rsurface.texture is the
10566                 // current frame/skin the texture is directing us to use (for example
10567                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10568                 // use skin 1 instead)
10569                 texture = surfacelist[i]->texture;
10570                 rsurface.texture = R_GetCurrentTexture(texture);
10571                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10572                 {
10573                         // if this texture is not the kind we want, skip ahead to the next one
10574                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10575                                 ;
10576                         continue;
10577                 }
10578                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10579                 {
10580                         rsurface.lightmaptexture = NULL;
10581                         rsurface.deluxemaptexture = NULL;
10582                         rsurface.uselightmaptexture = false;
10583                         // simply scan ahead until we find a different texture or lightmap state
10584                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10585                                 ;
10586                 }
10587                 else
10588                 {
10589                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10590                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10591                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10592                         // simply scan ahead until we find a different texture or lightmap state
10593                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10594                                 ;
10595                 }
10596                 // render the range of surfaces
10597                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10598         }
10599         R_FrameData_ReturnToMark();
10600 }
10601
10602 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10603 {
10604         CHECKGLERROR
10605         if (depthonly)
10606                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10607         else if (prepass)
10608         {
10609                 if (!rsurface.texture->currentnumlayers)
10610                         return;
10611                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10612                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10613                 else
10614                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10615         }
10616         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10617                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10618         else if (!rsurface.texture->currentnumlayers)
10619                 return;
10620         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10621         {
10622                 // in the deferred case, transparent surfaces were queued during prepass
10623                 if (!r_shadow_usingdeferredprepass)
10624                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10625         }
10626         else
10627         {
10628                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10629                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10630         }
10631         CHECKGLERROR
10632 }
10633
10634 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10635 {
10636         int i, j;
10637         texture_t *texture;
10638         R_FrameData_SetMark();
10639         // break the surface list down into batches by texture and use of lightmapping
10640         for (i = 0;i < numsurfaces;i = j)
10641         {
10642                 j = i + 1;
10643                 // texture is the base texture pointer, rsurface.texture is the
10644                 // current frame/skin the texture is directing us to use (for example
10645                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10646                 // use skin 1 instead)
10647                 texture = surfacelist[i]->texture;
10648                 rsurface.texture = R_GetCurrentTexture(texture);
10649                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10650                 {
10651                         // if this texture is not the kind we want, skip ahead to the next one
10652                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10653                                 ;
10654                         continue;
10655                 }
10656                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10657                 {
10658                         rsurface.lightmaptexture = NULL;
10659                         rsurface.deluxemaptexture = NULL;
10660                         rsurface.uselightmaptexture = false;
10661                         // simply scan ahead until we find a different texture or lightmap state
10662                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10663                                 ;
10664                 }
10665                 else
10666                 {
10667                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10668                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10669                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10670                         // simply scan ahead until we find a different texture or lightmap state
10671                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10672                                 ;
10673                 }
10674                 // render the range of surfaces
10675                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10676         }
10677         R_FrameData_ReturnToMark();
10678 }
10679
10680 float locboxvertex3f[6*4*3] =
10681 {
10682         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10683         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10684         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10685         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10686         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10687         1,0,0, 0,0,0, 0,1,0, 1,1,0
10688 };
10689
10690 unsigned short locboxelements[6*2*3] =
10691 {
10692          0, 1, 2, 0, 2, 3,
10693          4, 5, 6, 4, 6, 7,
10694          8, 9,10, 8,10,11,
10695         12,13,14, 12,14,15,
10696         16,17,18, 16,18,19,
10697         20,21,22, 20,22,23
10698 };
10699
10700 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10701 {
10702         int i, j;
10703         cl_locnode_t *loc = (cl_locnode_t *)ent;
10704         vec3_t mins, size;
10705         float vertex3f[6*4*3];
10706         CHECKGLERROR
10707         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10708         GL_DepthMask(false);
10709         GL_DepthRange(0, 1);
10710         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10711         GL_DepthTest(true);
10712         GL_CullFace(GL_NONE);
10713         R_EntityMatrix(&identitymatrix);
10714
10715 //      R_Mesh_ResetTextureState();
10716
10717         i = surfacelist[0];
10718         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10719                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10720                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10721                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10722
10723         if (VectorCompare(loc->mins, loc->maxs))
10724         {
10725                 VectorSet(size, 2, 2, 2);
10726                 VectorMA(loc->mins, -0.5f, size, mins);
10727         }
10728         else
10729         {
10730                 VectorCopy(loc->mins, mins);
10731                 VectorSubtract(loc->maxs, loc->mins, size);
10732         }
10733
10734         for (i = 0;i < 6*4*3;)
10735                 for (j = 0;j < 3;j++, i++)
10736                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10737
10738         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10739         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10740         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10741 }
10742
10743 void R_DrawLocs(void)
10744 {
10745         int index;
10746         cl_locnode_t *loc, *nearestloc;
10747         vec3_t center;
10748         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10749         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10750         {
10751                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10752                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10753         }
10754 }
10755
10756 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10757 {
10758         if (decalsystem->decals)
10759                 Mem_Free(decalsystem->decals);
10760         memset(decalsystem, 0, sizeof(*decalsystem));
10761 }
10762
10763 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)
10764 {
10765         tridecal_t *decal;
10766         tridecal_t *decals;
10767         int i;
10768
10769         // expand or initialize the system
10770         if (decalsystem->maxdecals <= decalsystem->numdecals)
10771         {
10772                 decalsystem_t old = *decalsystem;
10773                 qboolean useshortelements;
10774                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10775                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10776                 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)));
10777                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10778                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10779                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10780                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10781                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10782                 if (decalsystem->numdecals)
10783                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10784                 if (old.decals)
10785                         Mem_Free(old.decals);
10786                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10787                         decalsystem->element3i[i] = i;
10788                 if (useshortelements)
10789                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10790                                 decalsystem->element3s[i] = i;
10791         }
10792
10793         // grab a decal and search for another free slot for the next one
10794         decals = decalsystem->decals;
10795         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10796         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10797                 ;
10798         decalsystem->freedecal = i;
10799         if (decalsystem->numdecals <= i)
10800                 decalsystem->numdecals = i + 1;
10801
10802         // initialize the decal
10803         decal->lived = 0;
10804         decal->triangleindex = triangleindex;
10805         decal->surfaceindex = surfaceindex;
10806         decal->decalsequence = decalsequence;
10807         decal->color4f[0][0] = c0[0];
10808         decal->color4f[0][1] = c0[1];
10809         decal->color4f[0][2] = c0[2];
10810         decal->color4f[0][3] = 1;
10811         decal->color4f[1][0] = c1[0];
10812         decal->color4f[1][1] = c1[1];
10813         decal->color4f[1][2] = c1[2];
10814         decal->color4f[1][3] = 1;
10815         decal->color4f[2][0] = c2[0];
10816         decal->color4f[2][1] = c2[1];
10817         decal->color4f[2][2] = c2[2];
10818         decal->color4f[2][3] = 1;
10819         decal->vertex3f[0][0] = v0[0];
10820         decal->vertex3f[0][1] = v0[1];
10821         decal->vertex3f[0][2] = v0[2];
10822         decal->vertex3f[1][0] = v1[0];
10823         decal->vertex3f[1][1] = v1[1];
10824         decal->vertex3f[1][2] = v1[2];
10825         decal->vertex3f[2][0] = v2[0];
10826         decal->vertex3f[2][1] = v2[1];
10827         decal->vertex3f[2][2] = v2[2];
10828         decal->texcoord2f[0][0] = t0[0];
10829         decal->texcoord2f[0][1] = t0[1];
10830         decal->texcoord2f[1][0] = t1[0];
10831         decal->texcoord2f[1][1] = t1[1];
10832         decal->texcoord2f[2][0] = t2[0];
10833         decal->texcoord2f[2][1] = t2[1];
10834         TriangleNormal(v0, v1, v2, decal->plane);
10835         VectorNormalize(decal->plane);
10836         decal->plane[3] = DotProduct(v0, decal->plane);
10837 }
10838
10839 extern cvar_t cl_decals_bias;
10840 extern cvar_t cl_decals_models;
10841 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10842 // baseparms, parms, temps
10843 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)
10844 {
10845         int cornerindex;
10846         int index;
10847         float v[9][3];
10848         const float *vertex3f;
10849         const float *normal3f;
10850         int numpoints;
10851         float points[2][9][3];
10852         float temp[3];
10853         float tc[9][2];
10854         float f;
10855         float c[9][4];
10856         const int *e;
10857
10858         e = rsurface.modelelement3i + 3*triangleindex;
10859
10860         vertex3f = rsurface.modelvertex3f;
10861         normal3f = rsurface.modelnormal3f;
10862
10863         if (normal3f)
10864         {
10865                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10866                 {
10867                         index = 3*e[cornerindex];
10868                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10869                 }
10870         }
10871         else
10872         {
10873                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10874                 {
10875                         index = 3*e[cornerindex];
10876                         VectorCopy(vertex3f + index, v[cornerindex]);
10877                 }
10878         }
10879
10880         // cull backfaces
10881         //TriangleNormal(v[0], v[1], v[2], normal);
10882         //if (DotProduct(normal, localnormal) < 0.0f)
10883         //      continue;
10884         // clip by each of the box planes formed from the projection matrix
10885         // if anything survives, we emit the decal
10886         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]);
10887         if (numpoints < 3)
10888                 return;
10889         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]);
10890         if (numpoints < 3)
10891                 return;
10892         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]);
10893         if (numpoints < 3)
10894                 return;
10895         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]);
10896         if (numpoints < 3)
10897                 return;
10898         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]);
10899         if (numpoints < 3)
10900                 return;
10901         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]);
10902         if (numpoints < 3)
10903                 return;
10904         // some part of the triangle survived, so we have to accept it...
10905         if (dynamic)
10906         {
10907                 // dynamic always uses the original triangle
10908                 numpoints = 3;
10909                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10910                 {
10911                         index = 3*e[cornerindex];
10912                         VectorCopy(vertex3f + index, v[cornerindex]);
10913                 }
10914         }
10915         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10916         {
10917                 // convert vertex positions to texcoords
10918                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10919                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10920                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10921                 // calculate distance fade from the projection origin
10922                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10923                 f = bound(0.0f, f, 1.0f);
10924                 c[cornerindex][0] = r * f;
10925                 c[cornerindex][1] = g * f;
10926                 c[cornerindex][2] = b * f;
10927                 c[cornerindex][3] = 1.0f;
10928                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10929         }
10930         if (dynamic)
10931                 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);
10932         else
10933                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10934                         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);
10935 }
10936 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)
10937 {
10938         matrix4x4_t projection;
10939         decalsystem_t *decalsystem;
10940         qboolean dynamic;
10941         dp_model_t *model;
10942         const msurface_t *surface;
10943         const msurface_t *surfaces;
10944         const int *surfacelist;
10945         const texture_t *texture;
10946         int numtriangles;
10947         int numsurfacelist;
10948         int surfacelistindex;
10949         int surfaceindex;
10950         int triangleindex;
10951         float localorigin[3];
10952         float localnormal[3];
10953         float localmins[3];
10954         float localmaxs[3];
10955         float localsize;
10956         //float normal[3];
10957         float planes[6][4];
10958         float angles[3];
10959         bih_t *bih;
10960         int bih_triangles_count;
10961         int bih_triangles[256];
10962         int bih_surfaces[256];
10963
10964         decalsystem = &ent->decalsystem;
10965         model = ent->model;
10966         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10967         {
10968                 R_DecalSystem_Reset(&ent->decalsystem);
10969                 return;
10970         }
10971
10972         if (!model->brush.data_leafs && !cl_decals_models.integer)
10973         {
10974                 if (decalsystem->model)
10975                         R_DecalSystem_Reset(decalsystem);
10976                 return;
10977         }
10978
10979         if (decalsystem->model != model)
10980                 R_DecalSystem_Reset(decalsystem);
10981         decalsystem->model = model;
10982
10983         RSurf_ActiveModelEntity(ent, true, false, false);
10984
10985         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10986         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10987         VectorNormalize(localnormal);
10988         localsize = worldsize*rsurface.inversematrixscale;
10989         localmins[0] = localorigin[0] - localsize;
10990         localmins[1] = localorigin[1] - localsize;
10991         localmins[2] = localorigin[2] - localsize;
10992         localmaxs[0] = localorigin[0] + localsize;
10993         localmaxs[1] = localorigin[1] + localsize;
10994         localmaxs[2] = localorigin[2] + localsize;
10995
10996         //VectorCopy(localnormal, planes[4]);
10997         //VectorVectors(planes[4], planes[2], planes[0]);
10998         AnglesFromVectors(angles, localnormal, NULL, false);
10999         AngleVectors(angles, planes[0], planes[2], planes[4]);
11000         VectorNegate(planes[0], planes[1]);
11001         VectorNegate(planes[2], planes[3]);
11002         VectorNegate(planes[4], planes[5]);
11003         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11004         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11005         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11006         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11007         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11008         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11009
11010 #if 1
11011 // works
11012 {
11013         matrix4x4_t forwardprojection;
11014         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11015         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11016 }
11017 #else
11018 // broken
11019 {
11020         float projectionvector[4][3];
11021         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11022         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11023         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11024         projectionvector[0][0] = planes[0][0] * ilocalsize;
11025         projectionvector[0][1] = planes[1][0] * ilocalsize;
11026         projectionvector[0][2] = planes[2][0] * ilocalsize;
11027         projectionvector[1][0] = planes[0][1] * ilocalsize;
11028         projectionvector[1][1] = planes[1][1] * ilocalsize;
11029         projectionvector[1][2] = planes[2][1] * ilocalsize;
11030         projectionvector[2][0] = planes[0][2] * ilocalsize;
11031         projectionvector[2][1] = planes[1][2] * ilocalsize;
11032         projectionvector[2][2] = planes[2][2] * ilocalsize;
11033         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11034         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11035         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11036         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11037 }
11038 #endif
11039
11040         dynamic = model->surfmesh.isanimated;
11041         numsurfacelist = model->nummodelsurfaces;
11042         surfacelist = model->sortedmodelsurfaces;
11043         surfaces = model->data_surfaces;
11044
11045         bih = NULL;
11046         bih_triangles_count = -1;
11047         if(!dynamic)
11048         {
11049                 if(model->render_bih.numleafs)
11050                         bih = &model->render_bih;
11051                 else if(model->collision_bih.numleafs)
11052                         bih = &model->collision_bih;
11053         }
11054         if(bih)
11055                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11056         if(bih_triangles_count == 0)
11057                 return;
11058         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11059                 return;
11060         if(bih_triangles_count > 0)
11061         {
11062                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11063                 {
11064                         surfaceindex = bih_surfaces[triangleindex];
11065                         surface = surfaces + surfaceindex;
11066                         texture = surface->texture;
11067                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11068                                 continue;
11069                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11070                                 continue;
11071                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11072                 }
11073         }
11074         else
11075         {
11076                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11077                 {
11078                         surfaceindex = surfacelist[surfacelistindex];
11079                         surface = surfaces + surfaceindex;
11080                         // check cull box first because it rejects more than any other check
11081                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11082                                 continue;
11083                         // skip transparent surfaces
11084                         texture = surface->texture;
11085                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11086                                 continue;
11087                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11088                                 continue;
11089                         numtriangles = surface->num_triangles;
11090                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11091                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11092                 }
11093         }
11094 }
11095
11096 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11097 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)
11098 {
11099         int renderentityindex;
11100         float worldmins[3];
11101         float worldmaxs[3];
11102         entity_render_t *ent;
11103
11104         if (!cl_decals_newsystem.integer)
11105                 return;
11106
11107         worldmins[0] = worldorigin[0] - worldsize;
11108         worldmins[1] = worldorigin[1] - worldsize;
11109         worldmins[2] = worldorigin[2] - worldsize;
11110         worldmaxs[0] = worldorigin[0] + worldsize;
11111         worldmaxs[1] = worldorigin[1] + worldsize;
11112         worldmaxs[2] = worldorigin[2] + worldsize;
11113
11114         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11115
11116         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11117         {
11118                 ent = r_refdef.scene.entities[renderentityindex];
11119                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11120                         continue;
11121
11122                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11123         }
11124 }
11125
11126 typedef struct r_decalsystem_splatqueue_s
11127 {
11128         vec3_t worldorigin;
11129         vec3_t worldnormal;
11130         float color[4];
11131         float tcrange[4];
11132         float worldsize;
11133         int decalsequence;
11134 }
11135 r_decalsystem_splatqueue_t;
11136
11137 int r_decalsystem_numqueued = 0;
11138 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11139
11140 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)
11141 {
11142         r_decalsystem_splatqueue_t *queue;
11143
11144         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11145                 return;
11146
11147         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11148         VectorCopy(worldorigin, queue->worldorigin);
11149         VectorCopy(worldnormal, queue->worldnormal);
11150         Vector4Set(queue->color, r, g, b, a);
11151         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11152         queue->worldsize = worldsize;
11153         queue->decalsequence = cl.decalsequence++;
11154 }
11155
11156 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11157 {
11158         int i;
11159         r_decalsystem_splatqueue_t *queue;
11160
11161         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11162                 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);
11163         r_decalsystem_numqueued = 0;
11164 }
11165
11166 extern cvar_t cl_decals_max;
11167 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11168 {
11169         int i;
11170         decalsystem_t *decalsystem = &ent->decalsystem;
11171         int numdecals;
11172         int killsequence;
11173         tridecal_t *decal;
11174         float frametime;
11175         float lifetime;
11176
11177         if (!decalsystem->numdecals)
11178                 return;
11179
11180         if (r_showsurfaces.integer)
11181                 return;
11182
11183         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11184         {
11185                 R_DecalSystem_Reset(decalsystem);
11186                 return;
11187         }
11188
11189         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11190         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11191
11192         if (decalsystem->lastupdatetime)
11193                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11194         else
11195                 frametime = 0;
11196         decalsystem->lastupdatetime = r_refdef.scene.time;
11197         decal = decalsystem->decals;
11198         numdecals = decalsystem->numdecals;
11199
11200         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11201         {
11202                 if (decal->color4f[0][3])
11203                 {
11204                         decal->lived += frametime;
11205                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11206                         {
11207                                 memset(decal, 0, sizeof(*decal));
11208                                 if (decalsystem->freedecal > i)
11209                                         decalsystem->freedecal = i;
11210                         }
11211                 }
11212         }
11213         decal = decalsystem->decals;
11214         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11215                 numdecals--;
11216
11217         // collapse the array by shuffling the tail decals into the gaps
11218         for (;;)
11219         {
11220                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11221                         decalsystem->freedecal++;
11222                 if (decalsystem->freedecal == numdecals)
11223                         break;
11224                 decal[decalsystem->freedecal] = decal[--numdecals];
11225         }
11226
11227         decalsystem->numdecals = numdecals;
11228
11229         if (numdecals <= 0)
11230         {
11231                 // if there are no decals left, reset decalsystem
11232                 R_DecalSystem_Reset(decalsystem);
11233         }
11234 }
11235
11236 extern skinframe_t *decalskinframe;
11237 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11238 {
11239         int i;
11240         decalsystem_t *decalsystem = &ent->decalsystem;
11241         int numdecals;
11242         tridecal_t *decal;
11243         float faderate;
11244         float alpha;
11245         float *v3f;
11246         float *c4f;
11247         float *t2f;
11248         const int *e;
11249         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11250         int numtris = 0;
11251
11252         numdecals = decalsystem->numdecals;
11253         if (!numdecals)
11254                 return;
11255
11256         if (r_showsurfaces.integer)
11257                 return;
11258
11259         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11260         {
11261                 R_DecalSystem_Reset(decalsystem);
11262                 return;
11263         }
11264
11265         // if the model is static it doesn't matter what value we give for
11266         // wantnormals and wanttangents, so this logic uses only rules applicable
11267         // to a model, knowing that they are meaningless otherwise
11268         if (ent == r_refdef.scene.worldentity)
11269                 RSurf_ActiveWorldEntity();
11270         else
11271                 RSurf_ActiveModelEntity(ent, false, false, false);
11272
11273         decalsystem->lastupdatetime = r_refdef.scene.time;
11274         decal = decalsystem->decals;
11275
11276         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11277
11278         // update vertex positions for animated models
11279         v3f = decalsystem->vertex3f;
11280         c4f = decalsystem->color4f;
11281         t2f = decalsystem->texcoord2f;
11282         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11283         {
11284                 if (!decal->color4f[0][3])
11285                         continue;
11286
11287                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11288                         continue;
11289
11290                 // skip backfaces
11291                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11292                         continue;
11293
11294                 // update color values for fading decals
11295                 if (decal->lived >= cl_decals_time.value)
11296                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11297                 else
11298                         alpha = 1.0f;
11299
11300                 c4f[ 0] = decal->color4f[0][0] * alpha;
11301                 c4f[ 1] = decal->color4f[0][1] * alpha;
11302                 c4f[ 2] = decal->color4f[0][2] * alpha;
11303                 c4f[ 3] = 1;
11304                 c4f[ 4] = decal->color4f[1][0] * alpha;
11305                 c4f[ 5] = decal->color4f[1][1] * alpha;
11306                 c4f[ 6] = decal->color4f[1][2] * alpha;
11307                 c4f[ 7] = 1;
11308                 c4f[ 8] = decal->color4f[2][0] * alpha;
11309                 c4f[ 9] = decal->color4f[2][1] * alpha;
11310                 c4f[10] = decal->color4f[2][2] * alpha;
11311                 c4f[11] = 1;
11312
11313                 t2f[0] = decal->texcoord2f[0][0];
11314                 t2f[1] = decal->texcoord2f[0][1];
11315                 t2f[2] = decal->texcoord2f[1][0];
11316                 t2f[3] = decal->texcoord2f[1][1];
11317                 t2f[4] = decal->texcoord2f[2][0];
11318                 t2f[5] = decal->texcoord2f[2][1];
11319
11320                 // update vertex positions for animated models
11321                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11322                 {
11323                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11324                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11325                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11326                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11327                 }
11328                 else
11329                 {
11330                         VectorCopy(decal->vertex3f[0], v3f);
11331                         VectorCopy(decal->vertex3f[1], v3f + 3);
11332                         VectorCopy(decal->vertex3f[2], v3f + 6);
11333                 }
11334
11335                 if (r_refdef.fogenabled)
11336                 {
11337                         alpha = RSurf_FogVertex(v3f);
11338                         VectorScale(c4f, alpha, c4f);
11339                         alpha = RSurf_FogVertex(v3f + 3);
11340                         VectorScale(c4f + 4, alpha, c4f + 4);
11341                         alpha = RSurf_FogVertex(v3f + 6);
11342                         VectorScale(c4f + 8, alpha, c4f + 8);
11343                 }
11344
11345                 v3f += 9;
11346                 c4f += 12;
11347                 t2f += 6;
11348                 numtris++;
11349         }
11350
11351         if (numtris > 0)
11352         {
11353                 r_refdef.stats.drawndecals += numtris;
11354
11355                 // now render the decals all at once
11356                 // (this assumes they all use one particle font texture!)
11357                 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);
11358 //              R_Mesh_ResetTextureState();
11359                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11360                 GL_DepthMask(false);
11361                 GL_DepthRange(0, 1);
11362                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11363                 GL_DepthTest(true);
11364                 GL_CullFace(GL_NONE);
11365                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11366                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11367                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11368         }
11369 }
11370
11371 static void R_DrawModelDecals(void)
11372 {
11373         int i, numdecals;
11374
11375         // fade faster when there are too many decals
11376         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11377         for (i = 0;i < r_refdef.scene.numentities;i++)
11378                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11379
11380         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11381         for (i = 0;i < r_refdef.scene.numentities;i++)
11382                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11383                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11384
11385         R_DecalSystem_ApplySplatEntitiesQueue();
11386
11387         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11388         for (i = 0;i < r_refdef.scene.numentities;i++)
11389                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11390
11391         r_refdef.stats.totaldecals += numdecals;
11392
11393         if (r_showsurfaces.integer)
11394                 return;
11395
11396         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11397
11398         for (i = 0;i < r_refdef.scene.numentities;i++)
11399         {
11400                 if (!r_refdef.viewcache.entityvisible[i])
11401                         continue;
11402                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11403                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11404         }
11405 }
11406
11407 extern cvar_t mod_collision_bih;
11408 void R_DrawDebugModel(void)
11409 {
11410         entity_render_t *ent = rsurface.entity;
11411         int i, j, k, l, flagsmask;
11412         const msurface_t *surface;
11413         dp_model_t *model = ent->model;
11414         vec3_t v;
11415
11416         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11417                 return;
11418
11419         if (r_showoverdraw.value > 0)
11420         {
11421                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11422                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11423                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11424                 GL_DepthTest(false);
11425                 GL_DepthMask(false);
11426                 GL_DepthRange(0, 1);
11427                 GL_BlendFunc(GL_ONE, GL_ONE);
11428                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11429                 {
11430                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11431                                 continue;
11432                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11433                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11434                         {
11435                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11436                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11437                                 if (!rsurface.texture->currentlayers->depthmask)
11438                                         GL_Color(c, 0, 0, 1.0f);
11439                                 else if (ent == r_refdef.scene.worldentity)
11440                                         GL_Color(c, c, c, 1.0f);
11441                                 else
11442                                         GL_Color(0, c, 0, 1.0f);
11443                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11444                                 RSurf_DrawBatch();
11445                         }
11446                 }
11447                 rsurface.texture = NULL;
11448         }
11449
11450         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11451
11452 //      R_Mesh_ResetTextureState();
11453         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11454         GL_DepthRange(0, 1);
11455         GL_DepthTest(!r_showdisabledepthtest.integer);
11456         GL_DepthMask(false);
11457         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11458
11459         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11460         {
11461                 int triangleindex;
11462                 int bihleafindex;
11463                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11464                 const q3mbrush_t *brush;
11465                 const bih_t *bih = &model->collision_bih;
11466                 const bih_leaf_t *bihleaf;
11467                 float vertex3f[3][3];
11468                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11469                 cullbox = false;
11470                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11471                 {
11472                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11473                                 continue;
11474                         switch (bihleaf->type)
11475                         {
11476                         case BIH_BRUSH:
11477                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11478                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11479                                 {
11480                                         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);
11481                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11482                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11483                                 }
11484                                 break;
11485                         case BIH_COLLISIONTRIANGLE:
11486                                 triangleindex = bihleaf->itemindex;
11487                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11488                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11489                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11490                                 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);
11491                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11492                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11493                                 break;
11494                         case BIH_RENDERTRIANGLE:
11495                                 triangleindex = bihleaf->itemindex;
11496                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11497                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11498                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11499                                 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);
11500                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11501                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11502                                 break;
11503                         }
11504                 }
11505         }
11506
11507         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11508
11509 #ifndef USE_GLES2
11510         if (r_showtris.integer && qglPolygonMode)
11511         {
11512                 if (r_showdisabledepthtest.integer)
11513                 {
11514                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11515                         GL_DepthMask(false);
11516                 }
11517                 else
11518                 {
11519                         GL_BlendFunc(GL_ONE, GL_ZERO);
11520                         GL_DepthMask(true);
11521                 }
11522                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11523                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11524                 {
11525                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11526                                 continue;
11527                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11528                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11529                         {
11530                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11531                                 if (!rsurface.texture->currentlayers->depthmask)
11532                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11533                                 else if (ent == r_refdef.scene.worldentity)
11534                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11535                                 else
11536                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11537                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11538                                 RSurf_DrawBatch();
11539                         }
11540                 }
11541                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11542                 rsurface.texture = NULL;
11543         }
11544
11545         if (r_shownormals.value != 0 && qglBegin)
11546         {
11547                 if (r_showdisabledepthtest.integer)
11548                 {
11549                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11550                         GL_DepthMask(false);
11551                 }
11552                 else
11553                 {
11554                         GL_BlendFunc(GL_ONE, GL_ZERO);
11555                         GL_DepthMask(true);
11556                 }
11557                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11558                 {
11559                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11560                                 continue;
11561                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11562                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11563                         {
11564                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11565                                 qglBegin(GL_LINES);
11566                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11567                                 {
11568                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11569                                         {
11570                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11571                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11572                                                 qglVertex3f(v[0], v[1], v[2]);
11573                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11574                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11575                                                 qglVertex3f(v[0], v[1], v[2]);
11576                                         }
11577                                 }
11578                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11579                                 {
11580                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11581                                         {
11582                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11583                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11584                                                 qglVertex3f(v[0], v[1], v[2]);
11585                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11586                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11587                                                 qglVertex3f(v[0], v[1], v[2]);
11588                                         }
11589                                 }
11590                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11591                                 {
11592                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11593                                         {
11594                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11595                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11596                                                 qglVertex3f(v[0], v[1], v[2]);
11597                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11598                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11599                                                 qglVertex3f(v[0], v[1], v[2]);
11600                                         }
11601                                 }
11602                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11603                                 {
11604                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11605                                         {
11606                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11607                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11608                                                 qglVertex3f(v[0], v[1], v[2]);
11609                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11610                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11611                                                 qglVertex3f(v[0], v[1], v[2]);
11612                                         }
11613                                 }
11614                                 qglEnd();
11615                                 CHECKGLERROR
11616                         }
11617                 }
11618                 rsurface.texture = NULL;
11619         }
11620 #endif
11621 }
11622
11623 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11624 int r_maxsurfacelist = 0;
11625 const msurface_t **r_surfacelist = NULL;
11626 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11627 {
11628         int i, j, endj, flagsmask;
11629         dp_model_t *model = r_refdef.scene.worldmodel;
11630         msurface_t *surfaces;
11631         unsigned char *update;
11632         int numsurfacelist = 0;
11633         if (model == NULL)
11634                 return;
11635
11636         if (r_maxsurfacelist < model->num_surfaces)
11637         {
11638                 r_maxsurfacelist = model->num_surfaces;
11639                 if (r_surfacelist)
11640                         Mem_Free((msurface_t**)r_surfacelist);
11641                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11642         }
11643
11644         RSurf_ActiveWorldEntity();
11645
11646         surfaces = model->data_surfaces;
11647         update = model->brushq1.lightmapupdateflags;
11648
11649         // update light styles on this submodel
11650         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11651         {
11652                 model_brush_lightstyleinfo_t *style;
11653                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11654                 {
11655                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11656                         {
11657                                 int *list = style->surfacelist;
11658                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11659                                 for (j = 0;j < style->numsurfaces;j++)
11660                                         update[list[j]] = true;
11661                         }
11662                 }
11663         }
11664
11665         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11666
11667         if (debug)
11668         {
11669                 R_DrawDebugModel();
11670                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11671                 return;
11672         }
11673
11674         rsurface.lightmaptexture = NULL;
11675         rsurface.deluxemaptexture = NULL;
11676         rsurface.uselightmaptexture = false;
11677         rsurface.texture = NULL;
11678         rsurface.rtlight = NULL;
11679         numsurfacelist = 0;
11680         // add visible surfaces to draw list
11681         for (i = 0;i < model->nummodelsurfaces;i++)
11682         {
11683                 j = model->sortedmodelsurfaces[i];
11684                 if (r_refdef.viewcache.world_surfacevisible[j])
11685                         r_surfacelist[numsurfacelist++] = surfaces + j;
11686         }
11687         // update lightmaps if needed
11688         if (model->brushq1.firstrender)
11689         {
11690                 model->brushq1.firstrender = false;
11691                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11692                         if (update[j])
11693                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11694         }
11695         else if (update)
11696         {
11697                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11698                         if (r_refdef.viewcache.world_surfacevisible[j])
11699                                 if (update[j])
11700                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11701         }
11702         // don't do anything if there were no surfaces
11703         if (!numsurfacelist)
11704         {
11705                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11706                 return;
11707         }
11708         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11709
11710         // add to stats if desired
11711         if (r_speeds.integer && !skysurfaces && !depthonly)
11712         {
11713                 r_refdef.stats.world_surfaces += numsurfacelist;
11714                 for (j = 0;j < numsurfacelist;j++)
11715                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11716         }
11717
11718         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11719 }
11720
11721 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11722 {
11723         int i, j, endj, flagsmask;
11724         dp_model_t *model = ent->model;
11725         msurface_t *surfaces;
11726         unsigned char *update;
11727         int numsurfacelist = 0;
11728         if (model == NULL)
11729                 return;
11730
11731         if (r_maxsurfacelist < model->num_surfaces)
11732         {
11733                 r_maxsurfacelist = model->num_surfaces;
11734                 if (r_surfacelist)
11735                         Mem_Free((msurface_t **)r_surfacelist);
11736                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11737         }
11738
11739         // if the model is static it doesn't matter what value we give for
11740         // wantnormals and wanttangents, so this logic uses only rules applicable
11741         // to a model, knowing that they are meaningless otherwise
11742         if (ent == r_refdef.scene.worldentity)
11743                 RSurf_ActiveWorldEntity();
11744         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11745                 RSurf_ActiveModelEntity(ent, false, false, false);
11746         else if (prepass)
11747                 RSurf_ActiveModelEntity(ent, true, true, true);
11748         else if (depthonly)
11749         {
11750                 switch (vid.renderpath)
11751                 {
11752                 case RENDERPATH_GL20:
11753                 case RENDERPATH_D3D9:
11754                 case RENDERPATH_D3D10:
11755                 case RENDERPATH_D3D11:
11756                 case RENDERPATH_SOFT:
11757                 case RENDERPATH_GLES2:
11758                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11759                         break;
11760                 case RENDERPATH_GL11:
11761                 case RENDERPATH_GL13:
11762                 case RENDERPATH_GLES1:
11763                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11764                         break;
11765                 }
11766         }
11767         else
11768         {
11769                 switch (vid.renderpath)
11770                 {
11771                 case RENDERPATH_GL20:
11772                 case RENDERPATH_D3D9:
11773                 case RENDERPATH_D3D10:
11774                 case RENDERPATH_D3D11:
11775                 case RENDERPATH_SOFT:
11776                 case RENDERPATH_GLES2:
11777                         RSurf_ActiveModelEntity(ent, true, true, false);
11778                         break;
11779                 case RENDERPATH_GL11:
11780                 case RENDERPATH_GL13:
11781                 case RENDERPATH_GLES1:
11782                         RSurf_ActiveModelEntity(ent, true, false, false);
11783                         break;
11784                 }
11785         }
11786
11787         surfaces = model->data_surfaces;
11788         update = model->brushq1.lightmapupdateflags;
11789
11790         // update light styles
11791         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11792         {
11793                 model_brush_lightstyleinfo_t *style;
11794                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11795                 {
11796                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11797                         {
11798                                 int *list = style->surfacelist;
11799                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11800                                 for (j = 0;j < style->numsurfaces;j++)
11801                                         update[list[j]] = true;
11802                         }
11803                 }
11804         }
11805
11806         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11807
11808         if (debug)
11809         {
11810                 R_DrawDebugModel();
11811                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11812                 return;
11813         }
11814
11815         rsurface.lightmaptexture = NULL;
11816         rsurface.deluxemaptexture = NULL;
11817         rsurface.uselightmaptexture = false;
11818         rsurface.texture = NULL;
11819         rsurface.rtlight = NULL;
11820         numsurfacelist = 0;
11821         // add visible surfaces to draw list
11822         for (i = 0;i < model->nummodelsurfaces;i++)
11823                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11824         // don't do anything if there were no surfaces
11825         if (!numsurfacelist)
11826         {
11827                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11828                 return;
11829         }
11830         // update lightmaps if needed
11831         if (update)
11832         {
11833                 int updated = 0;
11834                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11835                 {
11836                         if (update[j])
11837                         {
11838                                 updated++;
11839                                 R_BuildLightMap(ent, surfaces + j);
11840                         }
11841                 }
11842         }
11843         if (update)
11844                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11845                         if (update[j])
11846                                 R_BuildLightMap(ent, surfaces + j);
11847         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11848
11849         // add to stats if desired
11850         if (r_speeds.integer && !skysurfaces && !depthonly)
11851         {
11852                 r_refdef.stats.entities_surfaces += numsurfacelist;
11853                 for (j = 0;j < numsurfacelist;j++)
11854                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11855         }
11856
11857         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11858 }
11859
11860 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11861 {
11862         static texture_t texture;
11863         static msurface_t surface;
11864         const msurface_t *surfacelist = &surface;
11865
11866         // fake enough texture and surface state to render this geometry
11867
11868         texture.update_lastrenderframe = -1; // regenerate this texture
11869         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11870         texture.currentskinframe = skinframe;
11871         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11872         texture.offsetmapping = OFFSETMAPPING_OFF;
11873         texture.offsetscale = 1;
11874         texture.specularscalemod = 1;
11875         texture.specularpowermod = 1;
11876
11877         surface.texture = &texture;
11878         surface.num_triangles = numtriangles;
11879         surface.num_firsttriangle = firsttriangle;
11880         surface.num_vertices = numvertices;
11881         surface.num_firstvertex = firstvertex;
11882
11883         // now render it
11884         rsurface.texture = R_GetCurrentTexture(surface.texture);
11885         rsurface.lightmaptexture = NULL;
11886         rsurface.deluxemaptexture = NULL;
11887         rsurface.uselightmaptexture = false;
11888         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11889 }
11890
11891 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)
11892 {
11893         static msurface_t surface;
11894         const msurface_t *surfacelist = &surface;
11895
11896         // fake enough texture and surface state to render this geometry
11897         surface.texture = texture;
11898         surface.num_triangles = numtriangles;
11899         surface.num_firsttriangle = firsttriangle;
11900         surface.num_vertices = numvertices;
11901         surface.num_firstvertex = firstvertex;
11902
11903         // now render it
11904         rsurface.texture = R_GetCurrentTexture(surface.texture);
11905         rsurface.lightmaptexture = NULL;
11906         rsurface.deluxemaptexture = NULL;
11907         rsurface.uselightmaptexture = false;
11908         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11909 }