]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
removed cvars r_hdr and r_hdr_range - now the only way to get HDR
[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_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
201 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
202 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
203 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
204 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
205 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
206 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
207 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
208 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
209 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
210
211 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
212
213 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
214
215 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
216
217 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
218
219 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
220 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
221
222 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
223
224 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
225
226 extern cvar_t v_glslgamma;
227 extern cvar_t v_glslgamma_2d;
228
229 extern qboolean v_flipped_state;
230
231 r_framebufferstate_t r_fb;
232
233 /// shadow volume bsp struct with automatically growing nodes buffer
234 svbsp_t r_svbsp;
235
236 rtexture_t *r_texture_blanknormalmap;
237 rtexture_t *r_texture_white;
238 rtexture_t *r_texture_grey128;
239 rtexture_t *r_texture_black;
240 rtexture_t *r_texture_notexture;
241 rtexture_t *r_texture_whitecube;
242 rtexture_t *r_texture_normalizationcube;
243 rtexture_t *r_texture_fogattenuation;
244 rtexture_t *r_texture_fogheighttexture;
245 rtexture_t *r_texture_gammaramps;
246 unsigned int r_texture_gammaramps_serial;
247 //rtexture_t *r_texture_fogintensity;
248 rtexture_t *r_texture_reflectcube;
249
250 // TODO: hash lookups?
251 typedef struct cubemapinfo_s
252 {
253         char basename[64];
254         rtexture_t *texture;
255 }
256 cubemapinfo_t;
257
258 int r_texture_numcubemaps;
259 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
260
261 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
262 unsigned int r_numqueries;
263 unsigned int r_maxqueries;
264
265 typedef struct r_qwskincache_s
266 {
267         char name[MAX_QPATH];
268         skinframe_t *skinframe;
269 }
270 r_qwskincache_t;
271
272 static r_qwskincache_t *r_qwskincache;
273 static int r_qwskincache_size;
274
275 /// vertex coordinates for a quad that covers the screen exactly
276 extern const float r_screenvertex3f[12];
277 extern const float r_d3dscreenvertex3f[12];
278 const float r_screenvertex3f[12] =
279 {
280         0, 0, 0,
281         1, 0, 0,
282         1, 1, 0,
283         0, 1, 0
284 };
285 const float r_d3dscreenvertex3f[12] =
286 {
287         0, 1, 0,
288         1, 1, 0,
289         1, 0, 0,
290         0, 0, 0
291 };
292
293 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
294 {
295         int i;
296         for (i = 0;i < verts;i++)
297         {
298                 out[0] = in[0] * r;
299                 out[1] = in[1] * g;
300                 out[2] = in[2] * b;
301                 out[3] = in[3];
302                 in += 4;
303                 out += 4;
304         }
305 }
306
307 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
308 {
309         int i;
310         for (i = 0;i < verts;i++)
311         {
312                 out[0] = r;
313                 out[1] = g;
314                 out[2] = b;
315                 out[3] = a;
316                 out += 4;
317         }
318 }
319
320 // FIXME: move this to client?
321 void FOG_clear(void)
322 {
323         if (gamemode == GAME_NEHAHRA)
324         {
325                 Cvar_Set("gl_fogenable", "0");
326                 Cvar_Set("gl_fogdensity", "0.2");
327                 Cvar_Set("gl_fogred", "0.3");
328                 Cvar_Set("gl_foggreen", "0.3");
329                 Cvar_Set("gl_fogblue", "0.3");
330         }
331         r_refdef.fog_density = 0;
332         r_refdef.fog_red = 0;
333         r_refdef.fog_green = 0;
334         r_refdef.fog_blue = 0;
335         r_refdef.fog_alpha = 1;
336         r_refdef.fog_start = 0;
337         r_refdef.fog_end = 16384;
338         r_refdef.fog_height = 1<<30;
339         r_refdef.fog_fadedepth = 128;
340         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
341 }
342
343 static void R_BuildBlankTextures(void)
344 {
345         unsigned char data[4];
346         data[2] = 128; // normal X
347         data[1] = 128; // normal Y
348         data[0] = 255; // normal Z
349         data[3] = 255; // height
350         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
351         data[0] = 255;
352         data[1] = 255;
353         data[2] = 255;
354         data[3] = 255;
355         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 128;
357         data[1] = 128;
358         data[2] = 128;
359         data[3] = 255;
360         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361         data[0] = 0;
362         data[1] = 0;
363         data[2] = 0;
364         data[3] = 255;
365         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366 }
367
368 static void R_BuildNoTexture(void)
369 {
370         int x, y;
371         unsigned char pix[16][16][4];
372         // this makes a light grey/dark grey checkerboard texture
373         for (y = 0;y < 16;y++)
374         {
375                 for (x = 0;x < 16;x++)
376                 {
377                         if ((y < 8) ^ (x < 8))
378                         {
379                                 pix[y][x][0] = 128;
380                                 pix[y][x][1] = 128;
381                                 pix[y][x][2] = 128;
382                                 pix[y][x][3] = 255;
383                         }
384                         else
385                         {
386                                 pix[y][x][0] = 64;
387                                 pix[y][x][1] = 64;
388                                 pix[y][x][2] = 64;
389                                 pix[y][x][3] = 255;
390                         }
391                 }
392         }
393         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
394 }
395
396 static void R_BuildWhiteCube(void)
397 {
398         unsigned char data[6*1*1*4];
399         memset(data, 255, sizeof(data));
400         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
401 }
402
403 static void R_BuildNormalizationCube(void)
404 {
405         int x, y, side;
406         vec3_t v;
407         vec_t s, t, intensity;
408 #define NORMSIZE 64
409         unsigned char *data;
410         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
411         for (side = 0;side < 6;side++)
412         {
413                 for (y = 0;y < NORMSIZE;y++)
414                 {
415                         for (x = 0;x < NORMSIZE;x++)
416                         {
417                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
418                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
419                                 switch(side)
420                                 {
421                                 default:
422                                 case 0:
423                                         v[0] = 1;
424                                         v[1] = -t;
425                                         v[2] = -s;
426                                         break;
427                                 case 1:
428                                         v[0] = -1;
429                                         v[1] = -t;
430                                         v[2] = s;
431                                         break;
432                                 case 2:
433                                         v[0] = s;
434                                         v[1] = 1;
435                                         v[2] = t;
436                                         break;
437                                 case 3:
438                                         v[0] = s;
439                                         v[1] = -1;
440                                         v[2] = -t;
441                                         break;
442                                 case 4:
443                                         v[0] = s;
444                                         v[1] = -t;
445                                         v[2] = 1;
446                                         break;
447                                 case 5:
448                                         v[0] = -s;
449                                         v[1] = -t;
450                                         v[2] = -1;
451                                         break;
452                                 }
453                                 intensity = 127.0f / sqrt(DotProduct(v, v));
454                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
455                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
456                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
457                                 data[((side*64+y)*64+x)*4+3] = 255;
458                         }
459                 }
460         }
461         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
462         Mem_Free(data);
463 }
464
465 static void R_BuildFogTexture(void)
466 {
467         int x, b;
468 #define FOGWIDTH 256
469         unsigned char data1[FOGWIDTH][4];
470         //unsigned char data2[FOGWIDTH][4];
471         double d, r, alpha;
472
473         r_refdef.fogmasktable_start = r_refdef.fog_start;
474         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
475         r_refdef.fogmasktable_range = r_refdef.fogrange;
476         r_refdef.fogmasktable_density = r_refdef.fog_density;
477
478         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
479         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
480         {
481                 d = (x * r - r_refdef.fogmasktable_start);
482                 if(developer_extra.integer)
483                         Con_DPrintf("%f ", d);
484                 d = max(0, d);
485                 if (r_fog_exp2.integer)
486                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
487                 else
488                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
489                 if(developer_extra.integer)
490                         Con_DPrintf(" : %f ", alpha);
491                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
492                 if(developer_extra.integer)
493                         Con_DPrintf(" = %f\n", alpha);
494                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
495         }
496
497         for (x = 0;x < FOGWIDTH;x++)
498         {
499                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
500                 data1[x][0] = b;
501                 data1[x][1] = b;
502                 data1[x][2] = b;
503                 data1[x][3] = 255;
504                 //data2[x][0] = 255 - b;
505                 //data2[x][1] = 255 - b;
506                 //data2[x][2] = 255 - b;
507                 //data2[x][3] = 255;
508         }
509         if (r_texture_fogattenuation)
510         {
511                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
512                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
513         }
514         else
515         {
516                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
517                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
518         }
519 }
520
521 static void R_BuildFogHeightTexture(void)
522 {
523         unsigned char *inpixels;
524         int size;
525         int x;
526         int y;
527         int j;
528         float c[4];
529         float f;
530         inpixels = NULL;
531         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
532         if (r_refdef.fogheighttexturename[0])
533                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
534         if (!inpixels)
535         {
536                 r_refdef.fog_height_tablesize = 0;
537                 if (r_texture_fogheighttexture)
538                         R_FreeTexture(r_texture_fogheighttexture);
539                 r_texture_fogheighttexture = NULL;
540                 if (r_refdef.fog_height_table2d)
541                         Mem_Free(r_refdef.fog_height_table2d);
542                 r_refdef.fog_height_table2d = NULL;
543                 if (r_refdef.fog_height_table1d)
544                         Mem_Free(r_refdef.fog_height_table1d);
545                 r_refdef.fog_height_table1d = NULL;
546                 return;
547         }
548         size = image_width;
549         r_refdef.fog_height_tablesize = size;
550         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
551         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
552         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
553         Mem_Free(inpixels);
554         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
555         // average fog color table accounting for every fog layer between a point
556         // and the camera.  (Note: attenuation is handled separately!)
557         for (y = 0;y < size;y++)
558         {
559                 for (x = 0;x < size;x++)
560                 {
561                         Vector4Clear(c);
562                         f = 0;
563                         if (x < y)
564                         {
565                                 for (j = x;j <= y;j++)
566                                 {
567                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
568                                         f++;
569                                 }
570                         }
571                         else
572                         {
573                                 for (j = x;j >= y;j--)
574                                 {
575                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
576                                         f++;
577                                 }
578                         }
579                         f = 1.0f / f;
580                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
581                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
582                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
584                 }
585         }
586         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
587 }
588
589 //=======================================================================================================================================================
590
591 static const char *builtinshaderstring =
592 #include "shader_glsl.h"
593 ;
594
595 const char *builtinhlslshaderstring =
596 #include "shader_hlsl.h"
597 ;
598
599 char *glslshaderstring = NULL;
600 char *hlslshaderstring = NULL;
601
602 //=======================================================================================================================================================
603
604 typedef struct shaderpermutationinfo_s
605 {
606         const char *pretext;
607         const char *name;
608 }
609 shaderpermutationinfo_t;
610
611 typedef struct shadermodeinfo_s
612 {
613         const char *vertexfilename;
614         const char *geometryfilename;
615         const char *fragmentfilename;
616         const char *pretext;
617         const char *name;
618 }
619 shadermodeinfo_t;
620
621 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
622 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
623 {
624         {"#define USEDIFFUSE\n", " diffuse"},
625         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
626         {"#define USEVIEWTINT\n", " viewtint"},
627         {"#define USECOLORMAPPING\n", " colormapping"},
628         {"#define USESATURATION\n", " saturation"},
629         {"#define USEFOGINSIDE\n", " foginside"},
630         {"#define USEFOGOUTSIDE\n", " fogoutside"},
631         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
632         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
633         {"#define USEGAMMARAMPS\n", " gammaramps"},
634         {"#define USECUBEFILTER\n", " cubefilter"},
635         {"#define USEGLOW\n", " glow"},
636         {"#define USEBLOOM\n", " bloom"},
637         {"#define USESPECULAR\n", " specular"},
638         {"#define USEPOSTPROCESSING\n", " postprocessing"},
639         {"#define USEREFLECTION\n", " reflection"},
640         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
641         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
642         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
643         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
644         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
645         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
646         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
647         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
648         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
649         {"#define USEALPHAKILL\n", " alphakill"},
650         {"#define USEREFLECTCUBE\n", " reflectcube"},
651         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
652         {"#define USEBOUNCEGRID\n", " bouncegrid"},
653         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
654         {"#define USETRIPPY\n", " trippy"},
655 };
656
657 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
658 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
659 {
660         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
661         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
678 };
679
680 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
681 {
682         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
683         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 struct r_glsl_permutation_s;
703 typedef struct r_glsl_permutation_s
704 {
705         /// hash lookup data
706         struct r_glsl_permutation_s *hashnext;
707         unsigned int mode;
708         unsigned int permutation;
709
710         /// indicates if we have tried compiling this permutation already
711         qboolean compiled;
712         /// 0 if compilation failed
713         int program;
714         // texture units assigned to each detected uniform
715         int tex_Texture_First;
716         int tex_Texture_Second;
717         int tex_Texture_GammaRamps;
718         int tex_Texture_Normal;
719         int tex_Texture_Color;
720         int tex_Texture_Gloss;
721         int tex_Texture_Glow;
722         int tex_Texture_SecondaryNormal;
723         int tex_Texture_SecondaryColor;
724         int tex_Texture_SecondaryGloss;
725         int tex_Texture_SecondaryGlow;
726         int tex_Texture_Pants;
727         int tex_Texture_Shirt;
728         int tex_Texture_FogHeightTexture;
729         int tex_Texture_FogMask;
730         int tex_Texture_Lightmap;
731         int tex_Texture_Deluxemap;
732         int tex_Texture_Attenuation;
733         int tex_Texture_Cube;
734         int tex_Texture_Refraction;
735         int tex_Texture_Reflection;
736         int tex_Texture_ShadowMap2D;
737         int tex_Texture_CubeProjection;
738         int tex_Texture_ScreenDepth;
739         int tex_Texture_ScreenNormalMap;
740         int tex_Texture_ScreenDiffuse;
741         int tex_Texture_ScreenSpecular;
742         int tex_Texture_ReflectMask;
743         int tex_Texture_ReflectCube;
744         int tex_Texture_BounceGrid;
745         /// locations of detected uniforms in program object, or -1 if not found
746         int loc_Texture_First;
747         int loc_Texture_Second;
748         int loc_Texture_GammaRamps;
749         int loc_Texture_Normal;
750         int loc_Texture_Color;
751         int loc_Texture_Gloss;
752         int loc_Texture_Glow;
753         int loc_Texture_SecondaryNormal;
754         int loc_Texture_SecondaryColor;
755         int loc_Texture_SecondaryGloss;
756         int loc_Texture_SecondaryGlow;
757         int loc_Texture_Pants;
758         int loc_Texture_Shirt;
759         int loc_Texture_FogHeightTexture;
760         int loc_Texture_FogMask;
761         int loc_Texture_Lightmap;
762         int loc_Texture_Deluxemap;
763         int loc_Texture_Attenuation;
764         int loc_Texture_Cube;
765         int loc_Texture_Refraction;
766         int loc_Texture_Reflection;
767         int loc_Texture_ShadowMap2D;
768         int loc_Texture_CubeProjection;
769         int loc_Texture_ScreenDepth;
770         int loc_Texture_ScreenNormalMap;
771         int loc_Texture_ScreenDiffuse;
772         int loc_Texture_ScreenSpecular;
773         int loc_Texture_ReflectMask;
774         int loc_Texture_ReflectCube;
775         int loc_Texture_BounceGrid;
776         int loc_Alpha;
777         int loc_BloomBlur_Parameters;
778         int loc_ClientTime;
779         int loc_Color_Ambient;
780         int loc_Color_Diffuse;
781         int loc_Color_Specular;
782         int loc_Color_Glow;
783         int loc_Color_Pants;
784         int loc_Color_Shirt;
785         int loc_DeferredColor_Ambient;
786         int loc_DeferredColor_Diffuse;
787         int loc_DeferredColor_Specular;
788         int loc_DeferredMod_Diffuse;
789         int loc_DeferredMod_Specular;
790         int loc_DistortScaleRefractReflect;
791         int loc_EyePosition;
792         int loc_FogColor;
793         int loc_FogHeightFade;
794         int loc_FogPlane;
795         int loc_FogPlaneViewDist;
796         int loc_FogRangeRecip;
797         int loc_LightColor;
798         int loc_LightDir;
799         int loc_LightPosition;
800         int loc_OffsetMapping_ScaleSteps;
801         int loc_OffsetMapping_LodDistance;
802         int loc_OffsetMapping_Bias;
803         int loc_PixelSize;
804         int loc_ReflectColor;
805         int loc_ReflectFactor;
806         int loc_ReflectOffset;
807         int loc_RefractColor;
808         int loc_Saturation;
809         int loc_ScreenCenterRefractReflect;
810         int loc_ScreenScaleRefractReflect;
811         int loc_ScreenToDepth;
812         int loc_ShadowMap_Parameters;
813         int loc_ShadowMap_TextureScale;
814         int loc_SpecularPower;
815         int loc_UserVec1;
816         int loc_UserVec2;
817         int loc_UserVec3;
818         int loc_UserVec4;
819         int loc_ViewTintColor;
820         int loc_ViewToLight;
821         int loc_ModelToLight;
822         int loc_TexMatrix;
823         int loc_BackgroundTexMatrix;
824         int loc_ModelViewProjectionMatrix;
825         int loc_ModelViewMatrix;
826         int loc_PixelToScreenTexCoord;
827         int loc_ModelToReflectCube;
828         int loc_ShadowMapMatrix;
829         int loc_BloomColorSubtract;
830         int loc_NormalmapScrollBlend;
831         int loc_BounceGridMatrix;
832         int loc_BounceGridIntensity;
833 }
834 r_glsl_permutation_t;
835
836 #define SHADERPERMUTATION_HASHSIZE 256
837
838
839 // non-degradable "lightweight" shader parameters to keep the permutations simpler
840 // these can NOT degrade! only use for simple stuff
841 enum
842 {
843         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
844         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
845         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
846         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
847         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
849         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
850         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
851 };
852 #define SHADERSTATICPARMS_COUNT 8
853
854 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
855 static int shaderstaticparms_count = 0;
856
857 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
858 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
859 qboolean R_CompileShader_CheckStaticParms(void)
860 {
861         static int r_compileshader_staticparms_save[1];
862         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
863         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
864
865         // detect all
866         if (r_glsl_saturation_redcompensate.integer)
867                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
868         if (r_glsl_vertextextureblend_usebothalphas.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
870         if (r_shadow_glossexact.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
872         if (r_glsl_postprocess.integer)
873         {
874                 if (r_glsl_postprocess_uservec1_enable.integer)
875                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
876                 if (r_glsl_postprocess_uservec2_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
878                 if (r_glsl_postprocess_uservec3_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
880                 if (r_glsl_postprocess_uservec4_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
882         }
883         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
885         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
886 }
887
888 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
889         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
890                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
891         else \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
893 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
894 {
895         shaderstaticparms_count = 0;
896
897         // emit all
898         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
899         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
906 }
907
908 /// information about each possible shader permutation
909 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
910 /// currently selected permutation
911 r_glsl_permutation_t *r_glsl_permutation;
912 /// storage for permutations linked in the hash table
913 memexpandablearray_t r_glsl_permutationarray;
914
915 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
916 {
917         //unsigned int hashdepth = 0;
918         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
919         r_glsl_permutation_t *p;
920         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
921         {
922                 if (p->mode == mode && p->permutation == permutation)
923                 {
924                         //if (hashdepth > 10)
925                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
926                         return p;
927                 }
928                 //hashdepth++;
929         }
930         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
931         p->mode = mode;
932         p->permutation = permutation;
933         p->hashnext = r_glsl_permutationhash[mode][hashindex];
934         r_glsl_permutationhash[mode][hashindex] = p;
935         //if (hashdepth > 10)
936         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
937         return p;
938 }
939
940 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
941 {
942         char *shaderstring;
943         if (!filename || !filename[0])
944                 return NULL;
945         if (!strcmp(filename, "glsl/default.glsl"))
946         {
947                 if (!glslshaderstring)
948                 {
949                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
950                         if (glslshaderstring)
951                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
952                         else
953                                 glslshaderstring = (char *)builtinshaderstring;
954                 }
955                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
956                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
957                 return shaderstring;
958         }
959         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
960         if (shaderstring)
961         {
962                 if (printfromdisknotice)
963                         Con_DPrintf("from disk %s... ", filename);
964                 return shaderstring;
965         }
966         return shaderstring;
967 }
968
969 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
970 {
971         int i;
972         int sampler;
973         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
974         char *vertexstring, *geometrystring, *fragmentstring;
975         char permutationname[256];
976         int vertstrings_count = 0;
977         int geomstrings_count = 0;
978         int fragstrings_count = 0;
979         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
980         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
981         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982
983         if (p->compiled)
984                 return;
985         p->compiled = true;
986         p->program = 0;
987
988         permutationname[0] = 0;
989         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
990         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
991         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
992
993         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
994
995         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
996         if(vid.support.gl20shaders130)
997         {
998                 vertstrings_list[vertstrings_count++] = "#version 130\n";
999                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1000                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1001                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1002                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1003                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1004         }
1005
1006         // the first pretext is which type of shader to compile as
1007         // (later these will all be bound together as a program object)
1008         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1009         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1010         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1011
1012         // the second pretext is the mode (for example a light source)
1013         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1014         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1015         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1016         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1017
1018         // now add all the permutation pretexts
1019         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1020         {
1021                 if (permutation & (1<<i))
1022                 {
1023                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1024                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1025                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1027                 }
1028                 else
1029                 {
1030                         // keep line numbers correct
1031                         vertstrings_list[vertstrings_count++] = "\n";
1032                         geomstrings_list[geomstrings_count++] = "\n";
1033                         fragstrings_list[fragstrings_count++] = "\n";
1034                 }
1035         }
1036
1037         // add static parms
1038         R_CompileShader_AddStaticParms(mode, permutation);
1039         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1040         vertstrings_count += shaderstaticparms_count;
1041         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         geomstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         fragstrings_count += shaderstaticparms_count;
1045
1046         // now append the shader text itself
1047         vertstrings_list[vertstrings_count++] = vertexstring;
1048         geomstrings_list[geomstrings_count++] = geometrystring;
1049         fragstrings_list[fragstrings_count++] = fragmentstring;
1050
1051         // if any sources were NULL, clear the respective list
1052         if (!vertexstring)
1053                 vertstrings_count = 0;
1054         if (!geometrystring)
1055                 geomstrings_count = 0;
1056         if (!fragmentstring)
1057                 fragstrings_count = 0;
1058
1059         // compile the shader program
1060         if (vertstrings_count + geomstrings_count + fragstrings_count)
1061                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1062         if (p->program)
1063         {
1064                 CHECKGLERROR
1065                 qglUseProgram(p->program);CHECKGLERROR
1066                 // look up all the uniform variable names we care about, so we don't
1067                 // have to look them up every time we set them
1068
1069                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1070                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1071                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1072                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1073                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1074                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1075                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1076                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1077                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1078                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1079                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1080                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1081                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1082                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1083                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1084                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1085                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1086                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1087                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1088                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1089                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1090                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1091                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1092                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1093                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1094                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1095                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1096                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1097                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1098                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1099                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1100                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1101                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1102                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1103                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1104                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1105                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1106                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1107                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1108                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1109                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1110                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1111                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1112                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1113                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1114                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1115                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1116                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1117                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1118                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1119                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1120                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1121                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1122                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1123                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1124                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1125                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1126                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1127                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1128                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1129                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1130                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1131                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1132                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1133                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1134                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1135                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1136                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1137                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1138                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1139                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1140                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1141                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1142                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1143                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1144                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1145                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1146                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1147                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1148                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1149                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1150                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1151                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1152                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1153                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1154                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1155                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1156                 // initialize the samplers to refer to the texture units we use
1157                 p->tex_Texture_First = -1;
1158                 p->tex_Texture_Second = -1;
1159                 p->tex_Texture_GammaRamps = -1;
1160                 p->tex_Texture_Normal = -1;
1161                 p->tex_Texture_Color = -1;
1162                 p->tex_Texture_Gloss = -1;
1163                 p->tex_Texture_Glow = -1;
1164                 p->tex_Texture_SecondaryNormal = -1;
1165                 p->tex_Texture_SecondaryColor = -1;
1166                 p->tex_Texture_SecondaryGloss = -1;
1167                 p->tex_Texture_SecondaryGlow = -1;
1168                 p->tex_Texture_Pants = -1;
1169                 p->tex_Texture_Shirt = -1;
1170                 p->tex_Texture_FogHeightTexture = -1;
1171                 p->tex_Texture_FogMask = -1;
1172                 p->tex_Texture_Lightmap = -1;
1173                 p->tex_Texture_Deluxemap = -1;
1174                 p->tex_Texture_Attenuation = -1;
1175                 p->tex_Texture_Cube = -1;
1176                 p->tex_Texture_Refraction = -1;
1177                 p->tex_Texture_Reflection = -1;
1178                 p->tex_Texture_ShadowMap2D = -1;
1179                 p->tex_Texture_CubeProjection = -1;
1180                 p->tex_Texture_ScreenDepth = -1;
1181                 p->tex_Texture_ScreenNormalMap = -1;
1182                 p->tex_Texture_ScreenDiffuse = -1;
1183                 p->tex_Texture_ScreenSpecular = -1;
1184                 p->tex_Texture_ReflectMask = -1;
1185                 p->tex_Texture_ReflectCube = -1;
1186                 p->tex_Texture_BounceGrid = -1;
1187                 sampler = 0;
1188                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1189                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1190                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1191                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1192                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1193                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1194                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1195                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1196                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1199                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1200                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1201                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1202                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1203                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1204                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1205                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1206                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1207                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1208                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1209                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1210                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1211                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1212                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1215                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1216                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1217                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1218                 CHECKGLERROR
1219                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1220         }
1221         else
1222                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1223
1224         // free the strings
1225         if (vertexstring)
1226                 Mem_Free(vertexstring);
1227         if (geometrystring)
1228                 Mem_Free(geometrystring);
1229         if (fragmentstring)
1230                 Mem_Free(fragmentstring);
1231 }
1232
1233 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1234 {
1235         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1236         if (r_glsl_permutation != perm)
1237         {
1238                 r_glsl_permutation = perm;
1239                 if (!r_glsl_permutation->program)
1240                 {
1241                         if (!r_glsl_permutation->compiled)
1242                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1243                         if (!r_glsl_permutation->program)
1244                         {
1245                                 // remove features until we find a valid permutation
1246                                 int i;
1247                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1248                                 {
1249                                         // reduce i more quickly whenever it would not remove any bits
1250                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1251                                         if (!(permutation & j))
1252                                                 continue;
1253                                         permutation -= j;
1254                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1255                                         if (!r_glsl_permutation->compiled)
1256                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1257                                         if (r_glsl_permutation->program)
1258                                                 break;
1259                                 }
1260                                 if (i >= SHADERPERMUTATION_COUNT)
1261                                 {
1262                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1263                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1264                                         qglUseProgram(0);CHECKGLERROR
1265                                         return; // no bit left to clear, entire mode is broken
1266                                 }
1267                         }
1268                 }
1269                 CHECKGLERROR
1270                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1271         }
1272         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1273         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1274         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1275 }
1276
1277 #ifdef SUPPORTD3D
1278
1279 #ifdef SUPPORTD3D
1280 #include <d3d9.h>
1281 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1282 extern D3DCAPS9 vid_d3d9caps;
1283 #endif
1284
1285 struct r_hlsl_permutation_s;
1286 typedef struct r_hlsl_permutation_s
1287 {
1288         /// hash lookup data
1289         struct r_hlsl_permutation_s *hashnext;
1290         unsigned int mode;
1291         unsigned int permutation;
1292
1293         /// indicates if we have tried compiling this permutation already
1294         qboolean compiled;
1295         /// NULL if compilation failed
1296         IDirect3DVertexShader9 *vertexshader;
1297         IDirect3DPixelShader9 *pixelshader;
1298 }
1299 r_hlsl_permutation_t;
1300
1301 typedef enum D3DVSREGISTER_e
1302 {
1303         D3DVSREGISTER_TexMatrix = 0, // float4x4
1304         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1305         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1306         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1307         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1308         D3DVSREGISTER_ModelToLight = 20, // float4x4
1309         D3DVSREGISTER_EyePosition = 24,
1310         D3DVSREGISTER_FogPlane = 25,
1311         D3DVSREGISTER_LightDir = 26,
1312         D3DVSREGISTER_LightPosition = 27,
1313 }
1314 D3DVSREGISTER_t;
1315
1316 typedef enum D3DPSREGISTER_e
1317 {
1318         D3DPSREGISTER_Alpha = 0,
1319         D3DPSREGISTER_BloomBlur_Parameters = 1,
1320         D3DPSREGISTER_ClientTime = 2,
1321         D3DPSREGISTER_Color_Ambient = 3,
1322         D3DPSREGISTER_Color_Diffuse = 4,
1323         D3DPSREGISTER_Color_Specular = 5,
1324         D3DPSREGISTER_Color_Glow = 6,
1325         D3DPSREGISTER_Color_Pants = 7,
1326         D3DPSREGISTER_Color_Shirt = 8,
1327         D3DPSREGISTER_DeferredColor_Ambient = 9,
1328         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1329         D3DPSREGISTER_DeferredColor_Specular = 11,
1330         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1331         D3DPSREGISTER_DeferredMod_Specular = 13,
1332         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1333         D3DPSREGISTER_EyePosition = 15, // unused
1334         D3DPSREGISTER_FogColor = 16,
1335         D3DPSREGISTER_FogHeightFade = 17,
1336         D3DPSREGISTER_FogPlane = 18,
1337         D3DPSREGISTER_FogPlaneViewDist = 19,
1338         D3DPSREGISTER_FogRangeRecip = 20,
1339         D3DPSREGISTER_LightColor = 21,
1340         D3DPSREGISTER_LightDir = 22, // unused
1341         D3DPSREGISTER_LightPosition = 23,
1342         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1343         D3DPSREGISTER_PixelSize = 25,
1344         D3DPSREGISTER_ReflectColor = 26,
1345         D3DPSREGISTER_ReflectFactor = 27,
1346         D3DPSREGISTER_ReflectOffset = 28,
1347         D3DPSREGISTER_RefractColor = 29,
1348         D3DPSREGISTER_Saturation = 30,
1349         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1350         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1351         D3DPSREGISTER_ScreenToDepth = 33,
1352         D3DPSREGISTER_ShadowMap_Parameters = 34,
1353         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1354         D3DPSREGISTER_SpecularPower = 36,
1355         D3DPSREGISTER_UserVec1 = 37,
1356         D3DPSREGISTER_UserVec2 = 38,
1357         D3DPSREGISTER_UserVec3 = 39,
1358         D3DPSREGISTER_UserVec4 = 40,
1359         D3DPSREGISTER_ViewTintColor = 41,
1360         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1361         D3DPSREGISTER_BloomColorSubtract = 43,
1362         D3DPSREGISTER_ViewToLight = 44, // float4x4
1363         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1364         D3DPSREGISTER_NormalmapScrollBlend = 52,
1365         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1366         D3DPSREGISTER_OffsetMapping_Bias = 54,
1367         // next at 54
1368 }
1369 D3DPSREGISTER_t;
1370
1371 /// information about each possible shader permutation
1372 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1373 /// currently selected permutation
1374 r_hlsl_permutation_t *r_hlsl_permutation;
1375 /// storage for permutations linked in the hash table
1376 memexpandablearray_t r_hlsl_permutationarray;
1377
1378 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1379 {
1380         //unsigned int hashdepth = 0;
1381         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1382         r_hlsl_permutation_t *p;
1383         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1384         {
1385                 if (p->mode == mode && p->permutation == permutation)
1386                 {
1387                         //if (hashdepth > 10)
1388                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1389                         return p;
1390                 }
1391                 //hashdepth++;
1392         }
1393         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1394         p->mode = mode;
1395         p->permutation = permutation;
1396         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1397         r_hlsl_permutationhash[mode][hashindex] = p;
1398         //if (hashdepth > 10)
1399         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1400         return p;
1401 }
1402
1403 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1404 {
1405         char *shaderstring;
1406         if (!filename || !filename[0])
1407                 return NULL;
1408         if (!strcmp(filename, "hlsl/default.hlsl"))
1409         {
1410                 if (!hlslshaderstring)
1411                 {
1412                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1413                         if (hlslshaderstring)
1414                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1415                         else
1416                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1417                 }
1418                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1419                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1420                 return shaderstring;
1421         }
1422         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423         if (shaderstring)
1424         {
1425                 if (printfromdisknotice)
1426                         Con_DPrintf("from disk %s... ", filename);
1427                 return shaderstring;
1428         }
1429         return shaderstring;
1430 }
1431
1432 #include <d3dx9.h>
1433 //#include <d3dx9shader.h>
1434 //#include <d3dx9mesh.h>
1435
1436 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1437 {
1438         DWORD *vsbin = NULL;
1439         DWORD *psbin = NULL;
1440         fs_offset_t vsbinsize;
1441         fs_offset_t psbinsize;
1442 //      IDirect3DVertexShader9 *vs = NULL;
1443 //      IDirect3DPixelShader9 *ps = NULL;
1444         ID3DXBuffer *vslog = NULL;
1445         ID3DXBuffer *vsbuffer = NULL;
1446         ID3DXConstantTable *vsconstanttable = NULL;
1447         ID3DXBuffer *pslog = NULL;
1448         ID3DXBuffer *psbuffer = NULL;
1449         ID3DXConstantTable *psconstanttable = NULL;
1450         int vsresult = 0;
1451         int psresult = 0;
1452         char temp[MAX_INPUTLINE];
1453         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1454         qboolean debugshader = gl_paranoid.integer != 0;
1455         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1456         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1457         if (!debugshader)
1458         {
1459                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1460                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1461         }
1462         if ((!vsbin && vertstring) || (!psbin && fragstring))
1463         {
1464                 const char* dllnames_d3dx9 [] =
1465                 {
1466                         "d3dx9_43.dll",
1467                         "d3dx9_42.dll",
1468                         "d3dx9_41.dll",
1469                         "d3dx9_40.dll",
1470                         "d3dx9_39.dll",
1471                         "d3dx9_38.dll",
1472                         "d3dx9_37.dll",
1473                         "d3dx9_36.dll",
1474                         "d3dx9_35.dll",
1475                         "d3dx9_34.dll",
1476                         "d3dx9_33.dll",
1477                         "d3dx9_32.dll",
1478                         "d3dx9_31.dll",
1479                         "d3dx9_30.dll",
1480                         "d3dx9_29.dll",
1481                         "d3dx9_28.dll",
1482                         "d3dx9_27.dll",
1483                         "d3dx9_26.dll",
1484                         "d3dx9_25.dll",
1485                         "d3dx9_24.dll",
1486                         NULL
1487                 };
1488                 dllhandle_t d3dx9_dll = NULL;
1489                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1490                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1491                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 dllfunction_t d3dx9_dllfuncs[] =
1493                 {
1494                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1495                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1496                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1497                         {NULL, NULL}
1498                 };
1499                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1500                 {
1501                         DWORD shaderflags = 0;
1502                         if (debugshader)
1503                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1504                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1505                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1506                         if (vertstring && vertstring[0])
1507                         {
1508                                 if (debugshader)
1509                                 {
1510 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1511 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1512                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1513                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1514                                 }
1515                                 else
1516                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1517                                 if (vsbuffer)
1518                                 {
1519                                         vsbinsize = vsbuffer->GetBufferSize();
1520                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1521                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1522                                         vsbuffer->Release();
1523                                 }
1524                                 if (vslog)
1525                                 {
1526                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1527                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1528                                         vslog->Release();
1529                                 }
1530                         }
1531                         if (fragstring && fragstring[0])
1532                         {
1533                                 if (debugshader)
1534                                 {
1535 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1536 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1537                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1538                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1539                                 }
1540                                 else
1541                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1542                                 if (psbuffer)
1543                                 {
1544                                         psbinsize = psbuffer->GetBufferSize();
1545                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1546                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1547                                         psbuffer->Release();
1548                                 }
1549                                 if (pslog)
1550                                 {
1551                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1552                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1553                                         pslog->Release();
1554                                 }
1555                         }
1556                         Sys_UnloadLibrary(&d3dx9_dll);
1557                 }
1558                 else
1559                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1560         }
1561         if (vsbin && psbin)
1562         {
1563                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1564                 if (FAILED(vsresult))
1565                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1566                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1567                 if (FAILED(psresult))
1568                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1569         }
1570         // free the shader data
1571         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1572         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1573 }
1574
1575 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1576 {
1577         int i;
1578         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1579         int vertstring_length = 0;
1580         int geomstring_length = 0;
1581         int fragstring_length = 0;
1582         char *t;
1583         char *vertexstring, *geometrystring, *fragmentstring;
1584         char *vertstring, *geomstring, *fragstring;
1585         char permutationname[256];
1586         char cachename[256];
1587         int vertstrings_count = 0;
1588         int geomstrings_count = 0;
1589         int fragstrings_count = 0;
1590         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1591         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1592         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593
1594         if (p->compiled)
1595                 return;
1596         p->compiled = true;
1597         p->vertexshader = NULL;
1598         p->pixelshader = NULL;
1599
1600         permutationname[0] = 0;
1601         cachename[0] = 0;
1602         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1603         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1604         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1605
1606         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1607         strlcat(cachename, "hlsl/", sizeof(cachename));
1608
1609         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1610         vertstrings_count = 0;
1611         geomstrings_count = 0;
1612         fragstrings_count = 0;
1613         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1614         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1615         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1616
1617         // the first pretext is which type of shader to compile as
1618         // (later these will all be bound together as a program object)
1619         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1620         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1621         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1622
1623         // the second pretext is the mode (for example a light source)
1624         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1625         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1626         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1627         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1628         strlcat(cachename, modeinfo->name, sizeof(cachename));
1629
1630         // now add all the permutation pretexts
1631         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1632         {
1633                 if (permutation & (1<<i))
1634                 {
1635                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1636                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1637                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1639                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1640                 }
1641                 else
1642                 {
1643                         // keep line numbers correct
1644                         vertstrings_list[vertstrings_count++] = "\n";
1645                         geomstrings_list[geomstrings_count++] = "\n";
1646                         fragstrings_list[fragstrings_count++] = "\n";
1647                 }
1648         }
1649
1650         // add static parms
1651         R_CompileShader_AddStaticParms(mode, permutation);
1652         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1653         vertstrings_count += shaderstaticparms_count;
1654         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         geomstrings_count += shaderstaticparms_count;
1656         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         fragstrings_count += shaderstaticparms_count;
1658
1659         // replace spaces in the cachename with _ characters
1660         for (i = 0;cachename[i];i++)
1661                 if (cachename[i] == ' ')
1662                         cachename[i] = '_';
1663
1664         // now append the shader text itself
1665         vertstrings_list[vertstrings_count++] = vertexstring;
1666         geomstrings_list[geomstrings_count++] = geometrystring;
1667         fragstrings_list[fragstrings_count++] = fragmentstring;
1668
1669         // if any sources were NULL, clear the respective list
1670         if (!vertexstring)
1671                 vertstrings_count = 0;
1672         if (!geometrystring)
1673                 geomstrings_count = 0;
1674         if (!fragmentstring)
1675                 fragstrings_count = 0;
1676
1677         vertstring_length = 0;
1678         for (i = 0;i < vertstrings_count;i++)
1679                 vertstring_length += strlen(vertstrings_list[i]);
1680         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1681         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1682                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1683
1684         geomstring_length = 0;
1685         for (i = 0;i < geomstrings_count;i++)
1686                 geomstring_length += strlen(geomstrings_list[i]);
1687         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1688         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1689                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1690
1691         fragstring_length = 0;
1692         for (i = 0;i < fragstrings_count;i++)
1693                 fragstring_length += strlen(fragstrings_list[i]);
1694         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1695         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1696                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1697
1698         // try to load the cached shader, or generate one
1699         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1700
1701         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1702                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1703         else
1704                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1705
1706         // free the strings
1707         if (vertstring)
1708                 Mem_Free(vertstring);
1709         if (geomstring)
1710                 Mem_Free(geomstring);
1711         if (fragstring)
1712                 Mem_Free(fragstring);
1713         if (vertexstring)
1714                 Mem_Free(vertexstring);
1715         if (geometrystring)
1716                 Mem_Free(geometrystring);
1717         if (fragmentstring)
1718                 Mem_Free(fragmentstring);
1719 }
1720
1721 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1722 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1723 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);}
1724 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);}
1725 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);}
1726 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);}
1727
1728 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1729 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1730 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);}
1731 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);}
1732 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);}
1733 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);}
1734
1735 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1736 {
1737         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1738         if (r_hlsl_permutation != perm)
1739         {
1740                 r_hlsl_permutation = perm;
1741                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1742                 {
1743                         if (!r_hlsl_permutation->compiled)
1744                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1745                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                         {
1747                                 // remove features until we find a valid permutation
1748                                 int i;
1749                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1750                                 {
1751                                         // reduce i more quickly whenever it would not remove any bits
1752                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1753                                         if (!(permutation & j))
1754                                                 continue;
1755                                         permutation -= j;
1756                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1757                                         if (!r_hlsl_permutation->compiled)
1758                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1759                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1760                                                 break;
1761                                 }
1762                                 if (i >= SHADERPERMUTATION_COUNT)
1763                                 {
1764                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1765                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1766                                         return; // no bit left to clear, entire mode is broken
1767                                 }
1768                         }
1769                 }
1770                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1771                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1772         }
1773         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1774         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1775         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1776 }
1777 #endif
1778
1779 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1780 {
1781         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1782         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1783         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1784         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1785 }
1786
1787 void R_GLSL_Restart_f(void)
1788 {
1789         unsigned int i, limit;
1790         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1791                 Mem_Free(glslshaderstring);
1792         glslshaderstring = NULL;
1793         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1794                 Mem_Free(hlslshaderstring);
1795         hlslshaderstring = NULL;
1796         switch(vid.renderpath)
1797         {
1798         case RENDERPATH_D3D9:
1799 #ifdef SUPPORTD3D
1800                 {
1801                         r_hlsl_permutation_t *p;
1802                         r_hlsl_permutation = NULL;
1803                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1804                         for (i = 0;i < limit;i++)
1805                         {
1806                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1807                                 {
1808                                         if (p->vertexshader)
1809                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1810                                         if (p->pixelshader)
1811                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1812                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1813                                 }
1814                         }
1815                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1816                 }
1817 #endif
1818                 break;
1819         case RENDERPATH_D3D10:
1820                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1821                 break;
1822         case RENDERPATH_D3D11:
1823                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1824                 break;
1825         case RENDERPATH_GL20:
1826         case RENDERPATH_GLES2:
1827                 {
1828                         r_glsl_permutation_t *p;
1829                         r_glsl_permutation = NULL;
1830                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1831                         for (i = 0;i < limit;i++)
1832                         {
1833                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1834                                 {
1835                                         GL_Backend_FreeProgram(p->program);
1836                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1837                                 }
1838                         }
1839                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1840                 }
1841                 break;
1842         case RENDERPATH_GL11:
1843         case RENDERPATH_GL13:
1844         case RENDERPATH_GLES1:
1845                 break;
1846         case RENDERPATH_SOFT:
1847                 break;
1848         }
1849 }
1850
1851 void R_GLSL_DumpShader_f(void)
1852 {
1853         int i;
1854         qfile_t *file;
1855
1856         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1857         if (file)
1858         {
1859                 FS_Print(file, "/* The engine may define the following macros:\n");
1860                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1861                 for (i = 0;i < SHADERMODE_COUNT;i++)
1862                         FS_Print(file, glslshadermodeinfo[i].pretext);
1863                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864                         FS_Print(file, shaderpermutationinfo[i].pretext);
1865                 FS_Print(file, "*/\n");
1866                 FS_Print(file, builtinshaderstring);
1867                 FS_Close(file);
1868                 Con_Printf("glsl/default.glsl written\n");
1869         }
1870         else
1871                 Con_Printf("failed to write to glsl/default.glsl\n");
1872
1873         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1874         if (file)
1875         {
1876                 FS_Print(file, "/* The engine may define the following macros:\n");
1877                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878                 for (i = 0;i < SHADERMODE_COUNT;i++)
1879                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1880                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881                         FS_Print(file, shaderpermutationinfo[i].pretext);
1882                 FS_Print(file, "*/\n");
1883                 FS_Print(file, builtinhlslshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("hlsl/default.hlsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1889 }
1890
1891 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1892 {
1893         unsigned int permutation = 0;
1894         if (r_trippy.integer && !notrippy)
1895                 permutation |= SHADERPERMUTATION_TRIPPY;
1896         permutation |= SHADERPERMUTATION_VIEWTINT;
1897         if (first)
1898                 permutation |= SHADERPERMUTATION_DIFFUSE;
1899         if (second)
1900                 permutation |= SHADERPERMUTATION_SPECULAR;
1901         if (texturemode == GL_MODULATE)
1902                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1903         else if (texturemode == GL_ADD)
1904                 permutation |= SHADERPERMUTATION_GLOW;
1905         else if (texturemode == GL_DECAL)
1906                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1907         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1908                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1909         if (!second)
1910                 texturemode = GL_MODULATE;
1911         if (vid.allowalphatocoverage)
1912                 GL_AlphaToCoverage(false);
1913         switch (vid.renderpath)
1914         {
1915         case RENDERPATH_D3D9:
1916 #ifdef SUPPORTD3D
1917                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1918                 R_Mesh_TexBind(GL20TU_FIRST , first );
1919                 R_Mesh_TexBind(GL20TU_SECOND, second);
1920                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1921                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1922 #endif
1923                 break;
1924         case RENDERPATH_D3D10:
1925                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1926                 break;
1927         case RENDERPATH_D3D11:
1928                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1929                 break;
1930         case RENDERPATH_GL20:
1931         case RENDERPATH_GLES2:
1932                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1933                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1934                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1935                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1936                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1937                 break;
1938         case RENDERPATH_GL13:
1939         case RENDERPATH_GLES1:
1940                 R_Mesh_TexBind(0, first );
1941                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1942                 R_Mesh_TexBind(1, second);
1943                 if (second)
1944                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1945                 break;
1946         case RENDERPATH_GL11:
1947                 R_Mesh_TexBind(0, first );
1948                 break;
1949         case RENDERPATH_SOFT:
1950                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1951                 R_Mesh_TexBind(GL20TU_FIRST , first );
1952                 R_Mesh_TexBind(GL20TU_SECOND, second);
1953                 break;
1954         }
1955 }
1956
1957 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1958 {
1959         unsigned int permutation = 0;
1960         if (r_trippy.integer && !notrippy)
1961                 permutation |= SHADERPERMUTATION_TRIPPY;
1962         if (vid.allowalphatocoverage)
1963                 GL_AlphaToCoverage(false);
1964         switch (vid.renderpath)
1965         {
1966         case RENDERPATH_D3D9:
1967 #ifdef SUPPORTD3D
1968                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1969 #endif
1970                 break;
1971         case RENDERPATH_D3D10:
1972                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_D3D11:
1975                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1976                 break;
1977         case RENDERPATH_GL20:
1978         case RENDERPATH_GLES2:
1979                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980                 break;
1981         case RENDERPATH_GL13:
1982         case RENDERPATH_GLES1:
1983                 R_Mesh_TexBind(0, 0);
1984                 R_Mesh_TexBind(1, 0);
1985                 break;
1986         case RENDERPATH_GL11:
1987                 R_Mesh_TexBind(0, 0);
1988                 break;
1989         case RENDERPATH_SOFT:
1990                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1991                 break;
1992         }
1993 }
1994
1995 void R_SetupShader_ShowDepth(qboolean notrippy)
1996 {
1997         int permutation = 0;
1998         if (r_trippy.integer && !notrippy)
1999                 permutation |= SHADERPERMUTATION_TRIPPY;
2000         if (vid.allowalphatocoverage)
2001                 GL_AlphaToCoverage(false);
2002         switch (vid.renderpath)
2003         {
2004         case RENDERPATH_D3D9:
2005 #ifdef SUPPORTHLSL
2006                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2007 #endif
2008                 break;
2009         case RENDERPATH_D3D10:
2010                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2011                 break;
2012         case RENDERPATH_D3D11:
2013                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2014                 break;
2015         case RENDERPATH_GL20:
2016         case RENDERPATH_GLES2:
2017                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2018                 break;
2019         case RENDERPATH_GL13:
2020         case RENDERPATH_GLES1:
2021                 break;
2022         case RENDERPATH_GL11:
2023                 break;
2024         case RENDERPATH_SOFT:
2025                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2026                 break;
2027         }
2028 }
2029
2030 extern qboolean r_shadow_usingdeferredprepass;
2031 extern cvar_t r_shadow_deferred_8bitrange;
2032 extern rtexture_t *r_shadow_attenuationgradienttexture;
2033 extern rtexture_t *r_shadow_attenuation2dtexture;
2034 extern rtexture_t *r_shadow_attenuation3dtexture;
2035 extern qboolean r_shadow_usingshadowmap2d;
2036 extern qboolean r_shadow_usingshadowmaportho;
2037 extern float r_shadow_shadowmap_texturescale[2];
2038 extern float r_shadow_shadowmap_parameters[4];
2039 extern qboolean r_shadow_shadowmapvsdct;
2040 extern qboolean r_shadow_shadowmapsampler;
2041 extern int r_shadow_shadowmappcf;
2042 extern rtexture_t *r_shadow_shadowmap2dtexture;
2043 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2044 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2045 extern matrix4x4_t r_shadow_shadowmapmatrix;
2046 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2047 extern int r_shadow_prepass_width;
2048 extern int r_shadow_prepass_height;
2049 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2050 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2051 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2052 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2053 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2054
2055 #define BLENDFUNC_ALLOWS_COLORMOD      1
2056 #define BLENDFUNC_ALLOWS_FOG           2
2057 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2058 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2059 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2060 static int R_BlendFuncFlags(int src, int dst)
2061 {
2062         int r = 0;
2063
2064         // a blendfunc allows colormod if:
2065         // a) it can never keep the destination pixel invariant, or
2066         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2067         // this is to prevent unintended side effects from colormod
2068
2069         // a blendfunc allows fog if:
2070         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2071         // this is to prevent unintended side effects from fog
2072
2073         // these checks are the output of fogeval.pl
2074
2075         r |= BLENDFUNC_ALLOWS_COLORMOD;
2076         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2077         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2078         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2079         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2084         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2085         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097
2098         return r;
2099 }
2100
2101 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)
2102 {
2103         // select a permutation of the lighting shader appropriate to this
2104         // combination of texture, entity, light source, and fogging, only use the
2105         // minimum features necessary to avoid wasting rendering time in the
2106         // fragment shader on features that are not being used
2107         unsigned int permutation = 0;
2108         unsigned int mode = 0;
2109         int blendfuncflags;
2110         static float dummy_colormod[3] = {1, 1, 1};
2111         float *colormod = rsurface.colormod;
2112         float m16f[16];
2113         matrix4x4_t tempmatrix;
2114         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2115         if (r_trippy.integer && !notrippy)
2116                 permutation |= SHADERPERMUTATION_TRIPPY;
2117         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2118                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2119         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2120                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2121         if (rsurfacepass == RSURFPASS_BACKGROUND)
2122         {
2123                 // distorted background
2124                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2125                 {
2126                         mode = SHADERMODE_WATER;
2127                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2128                         {
2129                                 // this is the right thing to do for wateralpha
2130                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2131                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2132                         }
2133                         else
2134                         {
2135                                 // this is the right thing to do for entity alpha
2136                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2137                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138                         }
2139                 }
2140                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2141                 {
2142                         mode = SHADERMODE_REFRACTION;
2143                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2144                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                 }
2146                 else
2147                 {
2148                         mode = SHADERMODE_GENERIC;
2149                         permutation |= SHADERPERMUTATION_DIFFUSE;
2150                         GL_BlendFunc(GL_ONE, GL_ZERO);
2151                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2152                 }
2153                 if (vid.allowalphatocoverage)
2154                         GL_AlphaToCoverage(false);
2155         }
2156         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2157         {
2158                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2159                 {
2160                         switch(rsurface.texture->offsetmapping)
2161                         {
2162                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2163                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2164                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_OFF: break;
2166                         }
2167                 }
2168                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2169                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2170                 // normalmap (deferred prepass), may use alpha test on diffuse
2171                 mode = SHADERMODE_DEFERREDGEOMETRY;
2172                 GL_BlendFunc(GL_ONE, GL_ZERO);
2173                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2174                 if (vid.allowalphatocoverage)
2175                         GL_AlphaToCoverage(false);
2176         }
2177         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2178         {
2179                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2180                 {
2181                         switch(rsurface.texture->offsetmapping)
2182                         {
2183                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2184                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2185                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_OFF: break;
2187                         }
2188                 }
2189                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2190                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2191                 // light source
2192                 mode = SHADERMODE_LIGHTSOURCE;
2193                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2194                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2195                 if (diffusescale > 0)
2196                         permutation |= SHADERPERMUTATION_DIFFUSE;
2197                 if (specularscale > 0)
2198                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2199                 if (r_refdef.fogenabled)
2200                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2201                 if (rsurface.texture->colormapping)
2202                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2203                 if (r_shadow_usingshadowmap2d)
2204                 {
2205                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2206                         if(r_shadow_shadowmapvsdct)
2207                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2208
2209                         if (r_shadow_shadowmapsampler)
2210                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2211                         if (r_shadow_shadowmappcf > 1)
2212                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2213                         else if (r_shadow_shadowmappcf)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2215                 }
2216                 if (rsurface.texture->reflectmasktexture)
2217                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2218                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2219                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2220                 if (vid.allowalphatocoverage)
2221                         GL_AlphaToCoverage(false);
2222         }
2223         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2224         {
2225                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2226                 {
2227                         switch(rsurface.texture->offsetmapping)
2228                         {
2229                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2230                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2231                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2232                         case OFFSETMAPPING_OFF: break;
2233                         }
2234                 }
2235                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2236                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2237                 // unshaded geometry (fullbright or ambient model lighting)
2238                 mode = SHADERMODE_FLATCOLOR;
2239                 ambientscale = diffusescale = specularscale = 0;
2240                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2241                         permutation |= SHADERPERMUTATION_GLOW;
2242                 if (r_refdef.fogenabled)
2243                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2244                 if (rsurface.texture->colormapping)
2245                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2246                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2247                 {
2248                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2249                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2250
2251                         if (r_shadow_shadowmapsampler)
2252                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2253                         if (r_shadow_shadowmappcf > 1)
2254                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2255                         else if (r_shadow_shadowmappcf)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2257                 }
2258                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2259                         permutation |= SHADERPERMUTATION_REFLECTION;
2260                 if (rsurface.texture->reflectmasktexture)
2261                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2262                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2263                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264                 // when using alphatocoverage, we don't need alphakill
2265                 if (vid.allowalphatocoverage)
2266                 {
2267                         if (r_transparent_alphatocoverage.integer)
2268                         {
2269                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2270                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2271                         }
2272                         else
2273                                 GL_AlphaToCoverage(false);
2274                 }
2275         }
2276         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2277         {
2278                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2279                 {
2280                         switch(rsurface.texture->offsetmapping)
2281                         {
2282                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2283                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2284                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_OFF: break;
2286                         }
2287                 }
2288                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2289                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2290                 // directional model lighting
2291                 mode = SHADERMODE_LIGHTDIRECTION;
2292                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2293                         permutation |= SHADERPERMUTATION_GLOW;
2294                 permutation |= SHADERPERMUTATION_DIFFUSE;
2295                 if (specularscale > 0)
2296                         permutation |= SHADERPERMUTATION_SPECULAR;
2297                 if (r_refdef.fogenabled)
2298                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2299                 if (rsurface.texture->colormapping)
2300                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2301                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2302                 {
2303                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2304                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2305
2306                         if (r_shadow_shadowmapsampler)
2307                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2308                         if (r_shadow_shadowmappcf > 1)
2309                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2310                         else if (r_shadow_shadowmappcf)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2312                 }
2313                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2314                         permutation |= SHADERPERMUTATION_REFLECTION;
2315                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2316                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2317                 if (rsurface.texture->reflectmasktexture)
2318                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2319                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2320                 {
2321                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2322                         if (r_shadow_bouncegriddirectional)
2323                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2324                 }
2325                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2326                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327                 // when using alphatocoverage, we don't need alphakill
2328                 if (vid.allowalphatocoverage)
2329                 {
2330                         if (r_transparent_alphatocoverage.integer)
2331                         {
2332                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2333                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2334                         }
2335                         else
2336                                 GL_AlphaToCoverage(false);
2337                 }
2338         }
2339         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2340         {
2341                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2342                 {
2343                         switch(rsurface.texture->offsetmapping)
2344                         {
2345                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2346                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2347                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_OFF: break;
2349                         }
2350                 }
2351                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2352                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2353                 // ambient model lighting
2354                 mode = SHADERMODE_LIGHTDIRECTION;
2355                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2356                         permutation |= SHADERPERMUTATION_GLOW;
2357                 if (r_refdef.fogenabled)
2358                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2359                 if (rsurface.texture->colormapping)
2360                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2361                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2362                 {
2363                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2364                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2365
2366                         if (r_shadow_shadowmapsampler)
2367                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2368                         if (r_shadow_shadowmappcf > 1)
2369                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2370                         else if (r_shadow_shadowmappcf)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2372                 }
2373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2374                         permutation |= SHADERPERMUTATION_REFLECTION;
2375                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2376                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2377                 if (rsurface.texture->reflectmasktexture)
2378                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2379                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2380                 {
2381                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2382                         if (r_shadow_bouncegriddirectional)
2383                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2384                 }
2385                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2386                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387                 // when using alphatocoverage, we don't need alphakill
2388                 if (vid.allowalphatocoverage)
2389                 {
2390                         if (r_transparent_alphatocoverage.integer)
2391                         {
2392                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2393                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2394                         }
2395                         else
2396                                 GL_AlphaToCoverage(false);
2397                 }
2398         }
2399         else
2400         {
2401                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2402                 {
2403                         switch(rsurface.texture->offsetmapping)
2404                         {
2405                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2406                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2407                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2408                         case OFFSETMAPPING_OFF: break;
2409                         }
2410                 }
2411                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2412                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2413                 // lightmapped wall
2414                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2415                         permutation |= SHADERPERMUTATION_GLOW;
2416                 if (r_refdef.fogenabled)
2417                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2418                 if (rsurface.texture->colormapping)
2419                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2420                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2421                 {
2422                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2423                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2424
2425                         if (r_shadow_shadowmapsampler)
2426                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2427                         if (r_shadow_shadowmappcf > 1)
2428                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2429                         else if (r_shadow_shadowmappcf)
2430                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2431                 }
2432                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2433                         permutation |= SHADERPERMUTATION_REFLECTION;
2434                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2435                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2436                 if (rsurface.texture->reflectmasktexture)
2437                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2438                 if (FAKELIGHT_ENABLED)
2439                 {
2440                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2441                         mode = SHADERMODE_FAKELIGHT;
2442                         permutation |= SHADERPERMUTATION_DIFFUSE;
2443                         if (specularscale > 0)
2444                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2445                 }
2446                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2447                 {
2448                         // deluxemapping (light direction texture)
2449                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2450                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2451                         else
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2453                         permutation |= SHADERPERMUTATION_DIFFUSE;
2454                         if (specularscale > 0)
2455                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2456                 }
2457                 else if (r_glsl_deluxemapping.integer >= 2)
2458                 {
2459                         // fake deluxemapping (uniform light direction in tangentspace)
2460                         if (rsurface.uselightmaptexture)
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2462                         else
2463                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2464                         permutation |= SHADERPERMUTATION_DIFFUSE;
2465                         if (specularscale > 0)
2466                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2467                 }
2468                 else if (rsurface.uselightmaptexture)
2469                 {
2470                         // ordinary lightmapping (q1bsp, q3bsp)
2471                         mode = SHADERMODE_LIGHTMAP;
2472                 }
2473                 else
2474                 {
2475                         // ordinary vertex coloring (q3bsp)
2476                         mode = SHADERMODE_VERTEXCOLOR;
2477                 }
2478                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2479                 {
2480                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2481                         if (r_shadow_bouncegriddirectional)
2482                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2483                 }
2484                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 // when using alphatocoverage, we don't need alphakill
2487                 if (vid.allowalphatocoverage)
2488                 {
2489                         if (r_transparent_alphatocoverage.integer)
2490                         {
2491                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2492                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2493                         }
2494                         else
2495                                 GL_AlphaToCoverage(false);
2496                 }
2497         }
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2499                 colormod = dummy_colormod;
2500         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2501                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2502         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2503                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2504         switch(vid.renderpath)
2505         {
2506         case RENDERPATH_D3D9:
2507 #ifdef SUPPORTD3D
2508                 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);
2509                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2510                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2511                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2512                 if (mode == SHADERMODE_LIGHTSOURCE)
2513                 {
2514                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2515                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2516                 }
2517                 else
2518                 {
2519                         if (mode == SHADERMODE_LIGHTDIRECTION)
2520                         {
2521                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2522                         }
2523                 }
2524                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2527                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2528                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2529
2530                 if (mode == SHADERMODE_LIGHTSOURCE)
2531                 {
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2537
2538                         // additive passes are only darkened by fog, not tinted
2539                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2540                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2541                 }
2542                 else
2543                 {
2544                         if (mode == SHADERMODE_FLATCOLOR)
2545                         {
2546                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2547                         }
2548                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2549                         {
2550                                 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]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2552                                 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);
2553                                 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);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2557                         }
2558                         else
2559                         {
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2562                                 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);
2563                                 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);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2565                         }
2566                         // additive passes are only darkened by fog, not tinted
2567                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2569                         else
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2571                         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);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2579                         if (mode == SHADERMODE_WATER)
2580                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2581                 }
2582                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2583                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2584                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2585                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2586                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2587                 if (rsurface.texture->pantstexture)
2588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2589                 else
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2591                 if (rsurface.texture->shirttexture)
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2593                 else
2594                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2595                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2600                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2601                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2602                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2604                         );
2605                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2607                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2608                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2609
2610                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2611                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2612                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2613                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2618                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2620                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2622                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2623                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2624                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2625                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2626                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2627                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2628                 {
2629                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2630                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2631                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2632                 }
2633                 else
2634                 {
2635                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2636                 }
2637 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2638 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2640                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2641                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2642                 {
2643                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2644                         if (rsurface.rtlight)
2645                         {
2646                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2647                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2648                         }
2649                 }
2650 #endif
2651                 break;
2652         case RENDERPATH_D3D10:
2653                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654                 break;
2655         case RENDERPATH_D3D11:
2656                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2657                 break;
2658         case RENDERPATH_GL20:
2659         case RENDERPATH_GLES2:
2660                 if (!vid.useinterleavedarrays)
2661                 {
2662                         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);
2663                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2664                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2670                 }
2671                 else
2672                 {
2673                         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);
2674                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2675                 }
2676                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2677                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2678                 if (mode == SHADERMODE_LIGHTSOURCE)
2679                 {
2680                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2681                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2682                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2683                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2684                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2685                         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);
2686         
2687                         // additive passes are only darkened by fog, not tinted
2688                         if (r_glsl_permutation->loc_FogColor >= 0)
2689                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2690                         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);
2691                 }
2692                 else
2693                 {
2694                         if (mode == SHADERMODE_FLATCOLOR)
2695                         {
2696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2697                         }
2698                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2699                         {
2700                                 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]);
2701                                 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]);
2702                                 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);
2703                                 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);
2704                                 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);
2705                                 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]);
2706                                 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]);
2707                         }
2708                         else
2709                         {
2710                                 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]);
2711                                 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]);
2712                                 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);
2713                                 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);
2714                                 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);
2715                         }
2716                         // additive passes are only darkened by fog, not tinted
2717                         if (r_glsl_permutation->loc_FogColor >= 0)
2718                         {
2719                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2720                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2721                                 else
2722                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2723                         }
2724                         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);
2725                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2726                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2727                         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]);
2728                         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]);
2729                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2730                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2731                         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);
2732                         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]);
2733                 }
2734                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2735                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2736                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2737                 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]);
2738                 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]);
2739
2740                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2741                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2742                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2743                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2744                 {
2745                         if (rsurface.texture->pantstexture)
2746                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2747                         else
2748                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2749                 }
2750                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2751                 {
2752                         if (rsurface.texture->shirttexture)
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2754                         else
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2756                 }
2757                 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]);
2758                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2759                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2760                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2761                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2762                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2763                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2764                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2766                         );
2767                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2768                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2769                 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]);
2770                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2771                 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);}
2772                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2773
2774                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2775                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2776                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2777                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2778                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2779                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2780                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2781                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2782                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2785                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2786                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2787                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2788                 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);
2789                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2790                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2791                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2792                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2793                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2794                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2795                 {
2796                         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);
2797                         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);
2798                         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);
2799                 }
2800                 else
2801                 {
2802                         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);
2803                 }
2804                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2805                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2806                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2807                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2808                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2809                 {
2810                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2811                         if (rsurface.rtlight)
2812                         {
2813                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2814                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2815                         }
2816                 }
2817                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2818                 CHECKGLERROR
2819                 break;
2820         case RENDERPATH_GL11:
2821         case RENDERPATH_GL13:
2822         case RENDERPATH_GLES1:
2823                 break;
2824         case RENDERPATH_SOFT:
2825                 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);
2826                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2827                 R_SetupShader_SetPermutationSoft(mode, permutation);
2828                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2829                 if (mode == SHADERMODE_LIGHTSOURCE)
2830                 {
2831                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2837         
2838                         // additive passes are only darkened by fog, not tinted
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2840                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2841                 }
2842                 else
2843                 {
2844                         if (mode == SHADERMODE_FLATCOLOR)
2845                         {
2846                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2847                         }
2848                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2849                         {
2850                                 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]);
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2852                                 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);
2853                                 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);
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2855                                 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]);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2857                         }
2858                         else
2859                         {
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2862                                 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);
2863                                 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);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2865                         }
2866                         // additive passes are only darkened by fog, not tinted
2867                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2869                         else
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2871                         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);
2872                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2873                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2874                         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]);
2875                         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]);
2876                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2877                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2878                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2879                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2880                 }
2881                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2882                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2883                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2884                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2885                 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]);
2886
2887                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2888                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2889                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2890                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2891                 {
2892                         if (rsurface.texture->pantstexture)
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2894                         else
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2896                 }
2897                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2898                 {
2899                         if (rsurface.texture->shirttexture)
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2901                         else
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2903                 }
2904                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2905                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2906                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2907                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2908                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2909                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2910                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2912                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2913                         );
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2916                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2917                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2918
2919                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2920                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2921                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2922                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2923                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2924                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2927                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2928                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2929                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2930                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2931                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2932                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2933                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2934                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2935                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2936                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2937                 {
2938                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2939                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2940                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2941                 }
2942                 else
2943                 {
2944                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2945                 }
2946 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2947 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2948                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2949                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2950                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2951                 {
2952                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2953                         if (rsurface.rtlight)
2954                         {
2955                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2956                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2957                         }
2958                 }
2959                 break;
2960         }
2961 }
2962
2963 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2964 {
2965         // select a permutation of the lighting shader appropriate to this
2966         // combination of texture, entity, light source, and fogging, only use the
2967         // minimum features necessary to avoid wasting rendering time in the
2968         // fragment shader on features that are not being used
2969         unsigned int permutation = 0;
2970         unsigned int mode = 0;
2971         const float *lightcolorbase = rtlight->currentcolor;
2972         float ambientscale = rtlight->ambientscale;
2973         float diffusescale = rtlight->diffusescale;
2974         float specularscale = rtlight->specularscale;
2975         // this is the location of the light in view space
2976         vec3_t viewlightorigin;
2977         // this transforms from view space (camera) to light space (cubemap)
2978         matrix4x4_t viewtolight;
2979         matrix4x4_t lighttoview;
2980         float viewtolight16f[16];
2981         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2982         // light source
2983         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2984         if (rtlight->currentcubemap != r_texture_whitecube)
2985                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2986         if (diffusescale > 0)
2987                 permutation |= SHADERPERMUTATION_DIFFUSE;
2988         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2989                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2990         if (r_shadow_usingshadowmap2d)
2991         {
2992                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2993                 if (r_shadow_shadowmapvsdct)
2994                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2995
2996                 if (r_shadow_shadowmapsampler)
2997                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2998                 if (r_shadow_shadowmappcf > 1)
2999                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3000                 else if (r_shadow_shadowmappcf)
3001                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3002         }
3003         if (vid.allowalphatocoverage)
3004                 GL_AlphaToCoverage(false);
3005         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3006         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3007         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3008         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3009         switch(vid.renderpath)
3010         {
3011         case RENDERPATH_D3D9:
3012 #ifdef SUPPORTD3D
3013                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3014                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3015                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3016                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3019                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3020                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3021                 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);
3022                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3023                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3024
3025                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3026                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3027                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3028                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3029                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3030                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3031 #endif
3032                 break;
3033         case RENDERPATH_D3D10:
3034                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3035                 break;
3036         case RENDERPATH_D3D11:
3037                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3038                 break;
3039         case RENDERPATH_GL20:
3040         case RENDERPATH_GLES2:
3041                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3042                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3043                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3044                 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);
3045                 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);
3046                 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);
3047                 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]);
3048                 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]);
3049                 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);
3050                 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]);
3051                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3052
3053                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3054                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3055                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3056                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3057                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3058                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3059                 break;
3060         case RENDERPATH_GL11:
3061         case RENDERPATH_GL13:
3062         case RENDERPATH_GLES1:
3063                 break;
3064         case RENDERPATH_SOFT:
3065                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3066                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3067                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3068                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3069                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3071                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3072                 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]);
3073                 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);
3074                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3075                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3076
3077                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3078                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3079                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3080                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3081                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3082                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3083                 break;
3084         }
3085 }
3086
3087 #define SKINFRAME_HASH 1024
3088
3089 typedef struct
3090 {
3091         int loadsequence; // incremented each level change
3092         memexpandablearray_t array;
3093         skinframe_t *hash[SKINFRAME_HASH];
3094 }
3095 r_skinframe_t;
3096 r_skinframe_t r_skinframe;
3097
3098 void R_SkinFrame_PrepareForPurge(void)
3099 {
3100         r_skinframe.loadsequence++;
3101         // wrap it without hitting zero
3102         if (r_skinframe.loadsequence >= 200)
3103                 r_skinframe.loadsequence = 1;
3104 }
3105
3106 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3107 {
3108         if (!skinframe)
3109                 return;
3110         // mark the skinframe as used for the purging code
3111         skinframe->loadsequence = r_skinframe.loadsequence;
3112 }
3113
3114 void R_SkinFrame_Purge(void)
3115 {
3116         int i;
3117         skinframe_t *s;
3118         for (i = 0;i < SKINFRAME_HASH;i++)
3119         {
3120                 for (s = r_skinframe.hash[i];s;s = s->next)
3121                 {
3122                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3123                         {
3124                                 if (s->merged == s->base)
3125                                         s->merged = NULL;
3126                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3127                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3128                                 R_PurgeTexture(s->merged);s->merged = NULL;
3129                                 R_PurgeTexture(s->base  );s->base   = NULL;
3130                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3131                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3132                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3133                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3134                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3135                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3136                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3137                                 s->loadsequence = 0;
3138                         }
3139                 }
3140         }
3141 }
3142
3143 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3144         skinframe_t *item;
3145         char basename[MAX_QPATH];
3146
3147         Image_StripImageExtension(name, basename, sizeof(basename));
3148
3149         if( last == NULL ) {
3150                 int hashindex;
3151                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3152                 item = r_skinframe.hash[hashindex];
3153         } else {
3154                 item = last->next;
3155         }
3156
3157         // linearly search through the hash bucket
3158         for( ; item ; item = item->next ) {
3159                 if( !strcmp( item->basename, basename ) ) {
3160                         return item;
3161                 }
3162         }
3163         return NULL;
3164 }
3165
3166 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3167 {
3168         skinframe_t *item;
3169         int hashindex;
3170         char basename[MAX_QPATH];
3171
3172         Image_StripImageExtension(name, basename, sizeof(basename));
3173
3174         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3175         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3176                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3177                         break;
3178
3179         if (!item) {
3180                 rtexture_t *dyntexture;
3181                 // check whether its a dynamic texture
3182                 dyntexture = CL_GetDynTexture( basename );
3183                 if (!add && !dyntexture)
3184                         return NULL;
3185                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3186                 memset(item, 0, sizeof(*item));
3187                 strlcpy(item->basename, basename, sizeof(item->basename));
3188                 item->base = dyntexture; // either NULL or dyntexture handle
3189                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3190                 item->comparewidth = comparewidth;
3191                 item->compareheight = compareheight;
3192                 item->comparecrc = comparecrc;
3193                 item->next = r_skinframe.hash[hashindex];
3194                 r_skinframe.hash[hashindex] = item;
3195         }
3196         else if (textureflags & TEXF_FORCE_RELOAD)
3197         {
3198                 rtexture_t *dyntexture;
3199                 // check whether its a dynamic texture
3200                 dyntexture = CL_GetDynTexture( basename );
3201                 if (!add && !dyntexture)
3202                         return NULL;
3203                 if (item->merged == item->base)
3204                         item->merged = NULL;
3205                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3206                 R_PurgeTexture(item->stain );item->stain  = NULL;
3207                 R_PurgeTexture(item->merged);item->merged = NULL;
3208                 R_PurgeTexture(item->base  );item->base   = NULL;
3209                 R_PurgeTexture(item->pants );item->pants  = NULL;
3210                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3211                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3212                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3213                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3214                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3215         R_PurgeTexture(item->reflect);item->reflect = NULL;
3216                 item->loadsequence = 0;
3217         }
3218         else if( item->base == NULL )
3219         {
3220                 rtexture_t *dyntexture;
3221                 // check whether its a dynamic texture
3222                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3223                 dyntexture = CL_GetDynTexture( basename );
3224                 item->base = dyntexture; // either NULL or dyntexture handle
3225         }
3226
3227         R_SkinFrame_MarkUsed(item);
3228         return item;
3229 }
3230
3231 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3232         { \
3233                 unsigned long long avgcolor[5], wsum; \
3234                 int pix, comp, w; \
3235                 avgcolor[0] = 0; \
3236                 avgcolor[1] = 0; \
3237                 avgcolor[2] = 0; \
3238                 avgcolor[3] = 0; \
3239                 avgcolor[4] = 0; \
3240                 wsum = 0; \
3241                 for(pix = 0; pix < cnt; ++pix) \
3242                 { \
3243                         w = 0; \
3244                         for(comp = 0; comp < 3; ++comp) \
3245                                 w += getpixel; \
3246                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3247                         { \
3248                                 ++wsum; \
3249                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3250                                 w = getpixel; \
3251                                 for(comp = 0; comp < 3; ++comp) \
3252                                         avgcolor[comp] += getpixel * w; \
3253                                 avgcolor[3] += w; \
3254                         } \
3255                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3256                         avgcolor[4] += getpixel; \
3257                 } \
3258                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3259                         avgcolor[3] = 1; \
3260                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3261                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3262                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3263                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3264         }
3265
3266 extern cvar_t gl_picmip;
3267 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3268 {
3269         int j;
3270         unsigned char *pixels;
3271         unsigned char *bumppixels;
3272         unsigned char *basepixels = NULL;
3273         int basepixels_width = 0;
3274         int basepixels_height = 0;
3275         skinframe_t *skinframe;
3276         rtexture_t *ddsbase = NULL;
3277         qboolean ddshasalpha = false;
3278         float ddsavgcolor[4];
3279         char basename[MAX_QPATH];
3280         int miplevel = R_PicmipForFlags(textureflags);
3281         int savemiplevel = miplevel;
3282         int mymiplevel;
3283
3284         if (cls.state == ca_dedicated)
3285                 return NULL;
3286
3287         // return an existing skinframe if already loaded
3288         // if loading of the first image fails, don't make a new skinframe as it
3289         // would cause all future lookups of this to be missing
3290         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3291         if (skinframe && skinframe->base)
3292                 return skinframe;
3293
3294         Image_StripImageExtension(name, basename, sizeof(basename));
3295
3296         // check for DDS texture file first
3297         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3298         {
3299                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3300                 if (basepixels == NULL)
3301                         return NULL;
3302         }
3303
3304         // FIXME handle miplevel
3305
3306         if (developer_loading.integer)
3307                 Con_Printf("loading skin \"%s\"\n", name);
3308
3309         // we've got some pixels to store, so really allocate this new texture now
3310         if (!skinframe)
3311                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3312         textureflags &= ~TEXF_FORCE_RELOAD;
3313         skinframe->stain = NULL;
3314         skinframe->merged = NULL;
3315         skinframe->base = NULL;
3316         skinframe->pants = NULL;
3317         skinframe->shirt = NULL;
3318         skinframe->nmap = NULL;
3319         skinframe->gloss = NULL;
3320         skinframe->glow = NULL;
3321         skinframe->fog = NULL;
3322         skinframe->reflect = NULL;
3323         skinframe->hasalpha = false;
3324
3325         if (ddsbase)
3326         {
3327                 skinframe->base = ddsbase;
3328                 skinframe->hasalpha = ddshasalpha;
3329                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3330                 if (r_loadfog && skinframe->hasalpha)
3331                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3332                 //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]);
3333         }
3334         else
3335         {
3336                 basepixels_width = image_width;
3337                 basepixels_height = image_height;
3338                 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);
3339                 if (textureflags & TEXF_ALPHA)
3340                 {
3341                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3342                         {
3343                                 if (basepixels[j] < 255)
3344                                 {
3345                                         skinframe->hasalpha = true;
3346                                         break;
3347                                 }
3348                         }
3349                         if (r_loadfog && skinframe->hasalpha)
3350                         {
3351                                 // has transparent pixels
3352                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3353                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3354                                 {
3355                                         pixels[j+0] = 255;
3356                                         pixels[j+1] = 255;
3357                                         pixels[j+2] = 255;
3358                                         pixels[j+3] = basepixels[j+3];
3359                                 }
3360                                 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);
3361                                 Mem_Free(pixels);
3362                         }
3363                 }
3364                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3365 #ifndef USE_GLES2
3366                 //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]);
3367                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3368                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3369                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3370                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3371 #endif
3372         }
3373
3374         if (r_loaddds)
3375         {
3376                 mymiplevel = savemiplevel;
3377                 if (r_loadnormalmap)
3378                         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);
3379                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3380                 if (r_loadgloss)
3381                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3382                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3383                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3384                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3385         }
3386
3387         // _norm is the name used by tenebrae and has been adopted as standard
3388         if (r_loadnormalmap && skinframe->nmap == NULL)
3389         {
3390                 mymiplevel = savemiplevel;
3391                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3392                 {
3393                         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);
3394                         Mem_Free(pixels);
3395                         pixels = NULL;
3396                 }
3397                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3398                 {
3399                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3400                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3401                         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);
3402                         Mem_Free(pixels);
3403                         Mem_Free(bumppixels);
3404                 }
3405                 else if (r_shadow_bumpscale_basetexture.value > 0)
3406                 {
3407                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3408                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3409                         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);
3410                         Mem_Free(pixels);
3411                 }
3412 #ifndef USE_GLES2
3413                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3414                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3415 #endif
3416         }
3417
3418         // _luma is supported only for tenebrae compatibility
3419         // _glow is the preferred name
3420         mymiplevel = savemiplevel;
3421         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))))
3422         {
3423                 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);
3424 #ifndef USE_GLES2
3425                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3426                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3427 #endif
3428                 Mem_Free(pixels);pixels = NULL;
3429         }
3430
3431         mymiplevel = savemiplevel;
3432         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3433         {
3434                 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);
3435 #ifndef USE_GLES2
3436                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3437                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3438 #endif
3439                 Mem_Free(pixels);
3440                 pixels = NULL;
3441         }
3442
3443         mymiplevel = savemiplevel;
3444         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3445         {
3446                 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);
3447 #ifndef USE_GLES2
3448                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3449                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3450 #endif
3451                 Mem_Free(pixels);
3452                 pixels = NULL;
3453         }
3454
3455         mymiplevel = savemiplevel;
3456         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3457         {
3458                 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);
3459 #ifndef USE_GLES2
3460                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3461                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3462 #endif
3463                 Mem_Free(pixels);
3464                 pixels = NULL;
3465         }
3466
3467         mymiplevel = savemiplevel;
3468         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3469         {
3470                 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);
3471 #ifndef USE_GLES2
3472                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3473                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3474 #endif
3475                 Mem_Free(pixels);
3476                 pixels = NULL;
3477         }
3478
3479         if (basepixels)
3480                 Mem_Free(basepixels);
3481
3482         return skinframe;
3483 }
3484
3485 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3486 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3487 {
3488         int i;
3489         unsigned char *temp1, *temp2;
3490         skinframe_t *skinframe;
3491
3492         if (cls.state == ca_dedicated)
3493                 return NULL;
3494
3495         // if already loaded just return it, otherwise make a new skinframe
3496         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3497         if (skinframe && skinframe->base)
3498                 return skinframe;
3499         textureflags &= ~TEXF_FORCE_RELOAD;
3500
3501         skinframe->stain = NULL;
3502         skinframe->merged = NULL;
3503         skinframe->base = NULL;
3504         skinframe->pants = NULL;
3505         skinframe->shirt = NULL;
3506         skinframe->nmap = NULL;
3507         skinframe->gloss = NULL;
3508         skinframe->glow = NULL;
3509         skinframe->fog = NULL;
3510         skinframe->reflect = NULL;
3511         skinframe->hasalpha = false;
3512
3513         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3514         if (!skindata)
3515                 return NULL;
3516
3517         if (developer_loading.integer)
3518                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3519
3520         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3521         {
3522                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3523                 temp2 = temp1 + width * height * 4;
3524                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3525                 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);
3526                 Mem_Free(temp1);
3527         }
3528         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3529         if (textureflags & TEXF_ALPHA)
3530         {
3531                 for (i = 3;i < width * height * 4;i += 4)
3532                 {
3533                         if (skindata[i] < 255)
3534                         {
3535                                 skinframe->hasalpha = true;
3536                                 break;
3537                         }
3538                 }
3539                 if (r_loadfog && skinframe->hasalpha)
3540                 {
3541                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3542                         memcpy(fogpixels, skindata, width * height * 4);
3543                         for (i = 0;i < width * height * 4;i += 4)
3544                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3545                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3546                         Mem_Free(fogpixels);
3547                 }
3548         }
3549
3550         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3551         //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]);
3552
3553         return skinframe;
3554 }
3555
3556 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3557 {
3558         int i;
3559         int featuresmask;
3560         skinframe_t *skinframe;
3561
3562         if (cls.state == ca_dedicated)
3563                 return NULL;
3564
3565         // if already loaded just return it, otherwise make a new skinframe
3566         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3567         if (skinframe && skinframe->base)
3568                 return skinframe;
3569         textureflags &= ~TEXF_FORCE_RELOAD;
3570
3571         skinframe->stain = NULL;
3572         skinframe->merged = NULL;
3573         skinframe->base = NULL;
3574         skinframe->pants = NULL;
3575         skinframe->shirt = NULL;
3576         skinframe->nmap = NULL;
3577         skinframe->gloss = NULL;
3578         skinframe->glow = NULL;
3579         skinframe->fog = NULL;
3580         skinframe->reflect = NULL;
3581         skinframe->hasalpha = false;
3582
3583         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3584         if (!skindata)
3585                 return NULL;
3586
3587         if (developer_loading.integer)
3588                 Con_Printf("loading quake skin \"%s\"\n", name);
3589
3590         // 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)
3591         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3592         memcpy(skinframe->qpixels, skindata, width*height);
3593         skinframe->qwidth = width;
3594         skinframe->qheight = height;
3595
3596         featuresmask = 0;
3597         for (i = 0;i < width * height;i++)
3598                 featuresmask |= palette_featureflags[skindata[i]];
3599
3600         skinframe->hasalpha = false;
3601         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3602         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3603         skinframe->qgeneratemerged = true;
3604         skinframe->qgeneratebase = skinframe->qhascolormapping;
3605         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3606
3607         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3608         //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]);
3609
3610         return skinframe;
3611 }
3612
3613 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3614 {
3615         int width;
3616         int height;
3617         unsigned char *skindata;
3618
3619         if (!skinframe->qpixels)
3620                 return;
3621
3622         if (!skinframe->qhascolormapping)
3623                 colormapped = false;
3624
3625         if (colormapped)
3626         {
3627                 if (!skinframe->qgeneratebase)
3628                         return;
3629         }
3630         else
3631         {
3632                 if (!skinframe->qgeneratemerged)
3633                         return;
3634         }
3635
3636         width = skinframe->qwidth;
3637         height = skinframe->qheight;
3638         skindata = skinframe->qpixels;
3639
3640         if (skinframe->qgeneratenmap)
3641         {
3642                 unsigned char *temp1, *temp2;
3643                 skinframe->qgeneratenmap = false;
3644                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3645                 temp2 = temp1 + width * height * 4;
3646                 // use either a custom palette or the quake palette
3647                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3648                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3649                 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);
3650                 Mem_Free(temp1);
3651         }
3652
3653         if (skinframe->qgenerateglow)
3654         {
3655                 skinframe->qgenerateglow = false;
3656                 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
3657         }
3658
3659         if (colormapped)
3660         {
3661                 skinframe->qgeneratebase = false;
3662                 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);
3663                 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);
3664                 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);
3665         }
3666         else
3667         {
3668                 skinframe->qgeneratemerged = false;
3669                 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);
3670         }
3671
3672         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3673         {
3674                 Mem_Free(skinframe->qpixels);
3675                 skinframe->qpixels = NULL;
3676         }
3677 }
3678
3679 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)
3680 {
3681         int i;
3682         skinframe_t *skinframe;
3683
3684         if (cls.state == ca_dedicated)
3685                 return NULL;
3686
3687         // if already loaded just return it, otherwise make a new skinframe
3688         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3689         if (skinframe && skinframe->base)
3690                 return skinframe;
3691         textureflags &= ~TEXF_FORCE_RELOAD;
3692
3693         skinframe->stain = NULL;
3694         skinframe->merged = NULL;
3695         skinframe->base = NULL;
3696         skinframe->pants = NULL;
3697         skinframe->shirt = NULL;
3698         skinframe->nmap = NULL;
3699         skinframe->gloss = NULL;
3700         skinframe->glow = NULL;
3701         skinframe->fog = NULL;
3702         skinframe->reflect = NULL;
3703         skinframe->hasalpha = false;
3704
3705         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3706         if (!skindata)
3707                 return NULL;
3708
3709         if (developer_loading.integer)
3710                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3711
3712         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3713         if (textureflags & TEXF_ALPHA)
3714         {
3715                 for (i = 0;i < width * height;i++)
3716                 {
3717                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3718                         {
3719                                 skinframe->hasalpha = true;
3720                                 break;
3721                         }
3722                 }
3723                 if (r_loadfog && skinframe->hasalpha)
3724                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3725         }
3726
3727         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3728         //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]);
3729
3730         return skinframe;
3731 }
3732
3733 skinframe_t *R_SkinFrame_LoadMissing(void)
3734 {
3735         skinframe_t *skinframe;
3736
3737         if (cls.state == ca_dedicated)
3738                 return NULL;
3739
3740         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3741         skinframe->stain = NULL;
3742         skinframe->merged = NULL;
3743         skinframe->base = NULL;
3744         skinframe->pants = NULL;
3745         skinframe->shirt = NULL;
3746         skinframe->nmap = NULL;
3747         skinframe->gloss = NULL;
3748         skinframe->glow = NULL;
3749         skinframe->fog = NULL;
3750         skinframe->reflect = NULL;
3751         skinframe->hasalpha = false;
3752
3753         skinframe->avgcolor[0] = rand() / RAND_MAX;
3754         skinframe->avgcolor[1] = rand() / RAND_MAX;
3755         skinframe->avgcolor[2] = rand() / RAND_MAX;
3756         skinframe->avgcolor[3] = 1;
3757
3758         return skinframe;
3759 }
3760
3761 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3762 typedef struct suffixinfo_s
3763 {
3764         const char *suffix;
3765         qboolean flipx, flipy, flipdiagonal;
3766 }
3767 suffixinfo_t;
3768 static suffixinfo_t suffix[3][6] =
3769 {
3770         {
3771                 {"px",   false, false, false},
3772                 {"nx",   false, false, false},
3773                 {"py",   false, false, false},
3774                 {"ny",   false, false, false},
3775                 {"pz",   false, false, false},
3776                 {"nz",   false, false, false}
3777         },
3778         {
3779                 {"posx", false, false, false},
3780                 {"negx", false, false, false},
3781                 {"posy", false, false, false},
3782                 {"negy", false, false, false},
3783                 {"posz", false, false, false},
3784                 {"negz", false, false, false}
3785         },
3786         {
3787                 {"rt",    true, false,  true},
3788                 {"lf",   false,  true,  true},
3789                 {"ft",    true,  true, false},
3790                 {"bk",   false, false, false},
3791                 {"up",    true, false,  true},
3792                 {"dn",    true, false,  true}
3793         }
3794 };
3795
3796 static int componentorder[4] = {0, 1, 2, 3};
3797
3798 rtexture_t *R_LoadCubemap(const char *basename)
3799 {
3800         int i, j, cubemapsize;
3801         unsigned char *cubemappixels, *image_buffer;
3802         rtexture_t *cubemaptexture;
3803         char name[256];
3804         // must start 0 so the first loadimagepixels has no requested width/height
3805         cubemapsize = 0;
3806         cubemappixels = NULL;
3807         cubemaptexture = NULL;
3808         // keep trying different suffix groups (posx, px, rt) until one loads
3809         for (j = 0;j < 3 && !cubemappixels;j++)
3810         {
3811                 // load the 6 images in the suffix group
3812                 for (i = 0;i < 6;i++)
3813                 {
3814                         // generate an image name based on the base and and suffix
3815                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3816                         // load it
3817                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3818                         {
3819                                 // an image loaded, make sure width and height are equal
3820                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3821                                 {
3822                                         // if this is the first image to load successfully, allocate the cubemap memory
3823                                         if (!cubemappixels && image_width >= 1)
3824                                         {
3825                                                 cubemapsize = image_width;
3826                                                 // note this clears to black, so unavailable sides are black
3827                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3828                                         }
3829                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3830                                         if (cubemappixels)
3831                                                 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);
3832                                 }
3833                                 else
3834                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3835                                 // free the image
3836                                 Mem_Free(image_buffer);
3837                         }
3838                 }
3839         }
3840         // if a cubemap loaded, upload it
3841         if (cubemappixels)
3842         {
3843                 if (developer_loading.integer)
3844                         Con_Printf("loading cubemap \"%s\"\n", basename);
3845
3846                 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);
3847                 Mem_Free(cubemappixels);
3848         }
3849         else
3850         {
3851                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3852                 if (developer_loading.integer)
3853                 {
3854                         Con_Printf("(tried tried images ");
3855                         for (j = 0;j < 3;j++)
3856                                 for (i = 0;i < 6;i++)
3857                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3858                         Con_Print(" and was unable to find any of them).\n");
3859                 }
3860         }
3861         return cubemaptexture;
3862 }
3863
3864 rtexture_t *R_GetCubemap(const char *basename)
3865 {
3866         int i;
3867         for (i = 0;i < r_texture_numcubemaps;i++)
3868                 if (r_texture_cubemaps[i] != NULL)
3869                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3870                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3871         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3872                 return r_texture_whitecube;
3873         r_texture_numcubemaps++;
3874         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3875         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3876         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3877         return r_texture_cubemaps[i]->texture;
3878 }
3879
3880 void R_FreeCubemap(const char *basename)
3881 {
3882         int i;
3883
3884         for (i = 0;i < r_texture_numcubemaps;i++)
3885         {
3886                 if (r_texture_cubemaps[i] != NULL)
3887                 {
3888                         if (r_texture_cubemaps[i]->texture)
3889                         {
3890                                 if (developer_loading.integer)
3891                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3892                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3893                                 Mem_Free(r_texture_cubemaps[i]);
3894                                 r_texture_cubemaps[i] = NULL;
3895                         }
3896                 }
3897         }
3898 }
3899
3900 void R_FreeCubemaps(void)
3901 {
3902         int i;
3903         for (i = 0;i < r_texture_numcubemaps;i++)
3904         {
3905                 if (developer_loading.integer)
3906                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3907                 if (r_texture_cubemaps[i] != NULL)
3908                 {
3909                         if (r_texture_cubemaps[i]->texture)
3910                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3911                         Mem_Free(r_texture_cubemaps[i]);
3912                 }
3913         }
3914         r_texture_numcubemaps = 0;
3915 }
3916
3917 void R_Main_FreeViewCache(void)
3918 {
3919         if (r_refdef.viewcache.entityvisible)
3920                 Mem_Free(r_refdef.viewcache.entityvisible);
3921         if (r_refdef.viewcache.world_pvsbits)
3922                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3923         if (r_refdef.viewcache.world_leafvisible)
3924                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3925         if (r_refdef.viewcache.world_surfacevisible)
3926                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3927         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3928 }
3929
3930 void R_Main_ResizeViewCache(void)
3931 {
3932         int numentities = r_refdef.scene.numentities;
3933         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3934         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3935         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3936         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3937         if (r_refdef.viewcache.maxentities < numentities)
3938         {
3939                 r_refdef.viewcache.maxentities = numentities;
3940                 if (r_refdef.viewcache.entityvisible)
3941                         Mem_Free(r_refdef.viewcache.entityvisible);
3942                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3943         }
3944         if (r_refdef.viewcache.world_numclusters != numclusters)
3945         {
3946                 r_refdef.viewcache.world_numclusters = numclusters;
3947                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3948                 if (r_refdef.viewcache.world_pvsbits)
3949                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3950                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3951         }
3952         if (r_refdef.viewcache.world_numleafs != numleafs)
3953         {
3954                 r_refdef.viewcache.world_numleafs = numleafs;
3955                 if (r_refdef.viewcache.world_leafvisible)
3956                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3957                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3958         }
3959         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3960         {
3961                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3962                 if (r_refdef.viewcache.world_surfacevisible)
3963                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3964                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3965         }
3966 }
3967
3968 extern rtexture_t *loadingscreentexture;
3969 void gl_main_start(void)
3970 {
3971         loadingscreentexture = NULL;
3972         r_texture_blanknormalmap = NULL;
3973         r_texture_white = NULL;
3974         r_texture_grey128 = NULL;
3975         r_texture_black = NULL;
3976         r_texture_whitecube = NULL;
3977         r_texture_normalizationcube = NULL;
3978         r_texture_fogattenuation = NULL;
3979         r_texture_fogheighttexture = NULL;
3980         r_texture_gammaramps = NULL;
3981         r_texture_numcubemaps = 0;
3982
3983         r_loaddds = r_texture_dds_load.integer != 0;
3984         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3985
3986         switch(vid.renderpath)
3987         {
3988         case RENDERPATH_GL20:
3989         case RENDERPATH_D3D9:
3990         case RENDERPATH_D3D10:
3991         case RENDERPATH_D3D11:
3992         case RENDERPATH_SOFT:
3993         case RENDERPATH_GLES2:
3994                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3995                 Cvar_SetValueQuick(&gl_combine, 1);
3996                 Cvar_SetValueQuick(&r_glsl, 1);
3997                 r_loadnormalmap = true;
3998                 r_loadgloss = true;
3999                 r_loadfog = false;
4000                 break;
4001         case RENDERPATH_GL13:
4002         case RENDERPATH_GLES1:
4003                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4004                 Cvar_SetValueQuick(&gl_combine, 1);
4005                 Cvar_SetValueQuick(&r_glsl, 0);
4006                 r_loadnormalmap = false;
4007                 r_loadgloss = false;
4008                 r_loadfog = true;
4009                 break;
4010         case RENDERPATH_GL11:
4011                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4012                 Cvar_SetValueQuick(&gl_combine, 0);
4013                 Cvar_SetValueQuick(&r_glsl, 0);
4014                 r_loadnormalmap = false;
4015                 r_loadgloss = false;
4016                 r_loadfog = true;
4017                 break;
4018         }
4019
4020         R_AnimCache_Free();
4021         R_FrameData_Reset();
4022
4023         r_numqueries = 0;
4024         r_maxqueries = 0;
4025         memset(r_queries, 0, sizeof(r_queries));
4026
4027         r_qwskincache = NULL;
4028         r_qwskincache_size = 0;
4029
4030         // due to caching of texture_t references, the collision cache must be reset
4031         Collision_Cache_Reset(true);
4032
4033         // set up r_skinframe loading system for textures
4034         memset(&r_skinframe, 0, sizeof(r_skinframe));
4035         r_skinframe.loadsequence = 1;
4036         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4037
4038         r_main_texturepool = R_AllocTexturePool();
4039         R_BuildBlankTextures();
4040         R_BuildNoTexture();
4041         if (vid.support.arb_texture_cube_map)
4042         {
4043                 R_BuildWhiteCube();
4044                 R_BuildNormalizationCube();
4045         }
4046         r_texture_fogattenuation = NULL;
4047         r_texture_fogheighttexture = NULL;
4048         r_texture_gammaramps = NULL;
4049         //r_texture_fogintensity = NULL;
4050         memset(&r_fb, 0, sizeof(r_fb));
4051         r_glsl_permutation = NULL;
4052         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4053         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4054         glslshaderstring = NULL;
4055 #ifdef SUPPORTD3D
4056         r_hlsl_permutation = NULL;
4057         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4058         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4059 #endif
4060         hlslshaderstring = NULL;
4061         memset(&r_svbsp, 0, sizeof (r_svbsp));
4062
4063         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4064         r_texture_numcubemaps = 0;
4065
4066         r_refdef.fogmasktable_density = 0;
4067 }
4068
4069 void gl_main_shutdown(void)
4070 {
4071         R_AnimCache_Free();
4072         R_FrameData_Reset();
4073
4074         R_Main_FreeViewCache();
4075
4076         switch(vid.renderpath)
4077         {
4078         case RENDERPATH_GL11:
4079         case RENDERPATH_GL13:
4080         case RENDERPATH_GL20:
4081         case RENDERPATH_GLES1:
4082         case RENDERPATH_GLES2:
4083 #ifdef GL_SAMPLES_PASSED_ARB
4084                 if (r_maxqueries)
4085                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4086 #endif
4087                 break;
4088         case RENDERPATH_D3D9:
4089                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090                 break;
4091         case RENDERPATH_D3D10:
4092                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4093                 break;
4094         case RENDERPATH_D3D11:
4095                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4096                 break;
4097         case RENDERPATH_SOFT:
4098                 break;
4099         }
4100
4101         r_numqueries = 0;
4102         r_maxqueries = 0;
4103         memset(r_queries, 0, sizeof(r_queries));
4104
4105         r_qwskincache = NULL;
4106         r_qwskincache_size = 0;
4107
4108         // clear out the r_skinframe state
4109         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4110         memset(&r_skinframe, 0, sizeof(r_skinframe));
4111
4112         if (r_svbsp.nodes)
4113                 Mem_Free(r_svbsp.nodes);
4114         memset(&r_svbsp, 0, sizeof (r_svbsp));
4115         R_FreeTexturePool(&r_main_texturepool);
4116         loadingscreentexture = NULL;
4117         r_texture_blanknormalmap = NULL;
4118         r_texture_white = NULL;
4119         r_texture_grey128 = NULL;
4120         r_texture_black = NULL;
4121         r_texture_whitecube = NULL;
4122         r_texture_normalizationcube = NULL;
4123         r_texture_fogattenuation = NULL;
4124         r_texture_fogheighttexture = NULL;
4125         r_texture_gammaramps = NULL;
4126         r_texture_numcubemaps = 0;
4127         //r_texture_fogintensity = NULL;
4128         memset(&r_fb, 0, sizeof(r_fb));
4129         R_GLSL_Restart_f();
4130
4131         r_glsl_permutation = NULL;
4132         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4133         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4134         glslshaderstring = NULL;
4135 #ifdef SUPPORTD3D
4136         r_hlsl_permutation = NULL;
4137         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4138         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4139 #endif
4140         hlslshaderstring = NULL;
4141 }
4142
4143 extern void CL_ParseEntityLump(char *entitystring);
4144 void gl_main_newmap(void)
4145 {
4146         // FIXME: move this code to client
4147         char *entities, entname[MAX_QPATH];
4148         if (r_qwskincache)
4149                 Mem_Free(r_qwskincache);
4150         r_qwskincache = NULL;
4151         r_qwskincache_size = 0;
4152         if (cl.worldmodel)
4153         {
4154                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4155                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4156                 {
4157                         CL_ParseEntityLump(entities);
4158                         Mem_Free(entities);
4159                         return;
4160                 }
4161                 if (cl.worldmodel->brush.entities)
4162                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4163         }
4164         R_Main_FreeViewCache();
4165
4166         R_FrameData_Reset();
4167 }
4168
4169 void GL_Main_Init(void)
4170 {
4171         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4172
4173         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4174         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4175         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4176         if (gamemode == GAME_NEHAHRA)
4177         {
4178                 Cvar_RegisterVariable (&gl_fogenable);
4179                 Cvar_RegisterVariable (&gl_fogdensity);
4180                 Cvar_RegisterVariable (&gl_fogred);
4181                 Cvar_RegisterVariable (&gl_foggreen);
4182                 Cvar_RegisterVariable (&gl_fogblue);
4183                 Cvar_RegisterVariable (&gl_fogstart);
4184                 Cvar_RegisterVariable (&gl_fogend);
4185                 Cvar_RegisterVariable (&gl_skyclip);
4186         }
4187         Cvar_RegisterVariable(&r_motionblur);
4188         Cvar_RegisterVariable(&r_damageblur);
4189         Cvar_RegisterVariable(&r_motionblur_averaging);
4190         Cvar_RegisterVariable(&r_motionblur_randomize);
4191         Cvar_RegisterVariable(&r_motionblur_minblur);
4192         Cvar_RegisterVariable(&r_motionblur_maxblur);
4193         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4194         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4195         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4196         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4197         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4198         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4199         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4200         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4201         Cvar_RegisterVariable(&r_equalize_entities_by);
4202         Cvar_RegisterVariable(&r_equalize_entities_to);
4203         Cvar_RegisterVariable(&r_depthfirst);
4204         Cvar_RegisterVariable(&r_useinfinitefarclip);
4205         Cvar_RegisterVariable(&r_farclip_base);
4206         Cvar_RegisterVariable(&r_farclip_world);
4207         Cvar_RegisterVariable(&r_nearclip);
4208         Cvar_RegisterVariable(&r_deformvertexes);
4209         Cvar_RegisterVariable(&r_transparent);
4210         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4211         Cvar_RegisterVariable(&r_showoverdraw);
4212         Cvar_RegisterVariable(&r_showbboxes);
4213         Cvar_RegisterVariable(&r_showsurfaces);
4214         Cvar_RegisterVariable(&r_showtris);
4215         Cvar_RegisterVariable(&r_shownormals);
4216         Cvar_RegisterVariable(&r_showlighting);
4217         Cvar_RegisterVariable(&r_showshadowvolumes);
4218         Cvar_RegisterVariable(&r_showcollisionbrushes);
4219         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4220         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4221         Cvar_RegisterVariable(&r_showdisabledepthtest);
4222         Cvar_RegisterVariable(&r_drawportals);
4223         Cvar_RegisterVariable(&r_drawentities);
4224         Cvar_RegisterVariable(&r_draw2d);
4225         Cvar_RegisterVariable(&r_drawworld);
4226         Cvar_RegisterVariable(&r_cullentities_trace);
4227         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4228         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4229         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4230         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4231         Cvar_RegisterVariable(&r_sortentities);
4232         Cvar_RegisterVariable(&r_drawviewmodel);
4233         Cvar_RegisterVariable(&r_drawexteriormodel);
4234         Cvar_RegisterVariable(&r_speeds);
4235         Cvar_RegisterVariable(&r_fullbrights);
4236         Cvar_RegisterVariable(&r_wateralpha);
4237         Cvar_RegisterVariable(&r_dynamic);
4238         Cvar_RegisterVariable(&r_fakelight);
4239         Cvar_RegisterVariable(&r_fakelight_intensity);
4240         Cvar_RegisterVariable(&r_fullbright);
4241         Cvar_RegisterVariable(&r_shadows);
4242         Cvar_RegisterVariable(&r_shadows_darken);
4243         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4244         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4245         Cvar_RegisterVariable(&r_shadows_throwdistance);
4246         Cvar_RegisterVariable(&r_shadows_throwdirection);
4247         Cvar_RegisterVariable(&r_shadows_focus);
4248         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4249         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4250         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4251         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4252         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4253         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4254         Cvar_RegisterVariable(&r_fog_exp2);
4255         Cvar_RegisterVariable(&r_fog_clear);
4256         Cvar_RegisterVariable(&r_drawfog);
4257         Cvar_RegisterVariable(&r_transparentdepthmasking);
4258         Cvar_RegisterVariable(&r_transparent_sortmindist);
4259         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4260         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4261         Cvar_RegisterVariable(&r_texture_dds_load);
4262         Cvar_RegisterVariable(&r_texture_dds_save);
4263         Cvar_RegisterVariable(&r_textureunits);
4264         Cvar_RegisterVariable(&gl_combine);
4265         Cvar_RegisterVariable(&r_viewfbo);
4266         Cvar_RegisterVariable(&r_viewscale);
4267         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4270         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4271         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4272         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4273         Cvar_RegisterVariable(&r_glsl);
4274         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4275         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4280         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4281         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4282         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4283         Cvar_RegisterVariable(&r_glsl_postprocess);
4284         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4289         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4290         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4291         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4292
4293         Cvar_RegisterVariable(&r_water);
4294         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4295         Cvar_RegisterVariable(&r_water_clippingplanebias);
4296         Cvar_RegisterVariable(&r_water_refractdistort);
4297         Cvar_RegisterVariable(&r_water_reflectdistort);
4298         Cvar_RegisterVariable(&r_water_scissormode);
4299         Cvar_RegisterVariable(&r_water_lowquality);
4300         Cvar_RegisterVariable(&r_water_hideplayer);
4301
4302         Cvar_RegisterVariable(&r_lerpsprites);
4303         Cvar_RegisterVariable(&r_lerpmodels);
4304         Cvar_RegisterVariable(&r_lerplightstyles);
4305         Cvar_RegisterVariable(&r_waterscroll);
4306         Cvar_RegisterVariable(&r_bloom);
4307         Cvar_RegisterVariable(&r_bloom_colorscale);
4308         Cvar_RegisterVariable(&r_bloom_brighten);
4309         Cvar_RegisterVariable(&r_bloom_blur);
4310         Cvar_RegisterVariable(&r_bloom_resolution);
4311         Cvar_RegisterVariable(&r_bloom_colorexponent);
4312         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4313         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4314         Cvar_RegisterVariable(&r_hdr_glowintensity);
4315         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4316         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4317         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4323         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4324         Cvar_RegisterVariable(&developer_texturelogging);
4325         Cvar_RegisterVariable(&gl_lightmaps);
4326         Cvar_RegisterVariable(&r_test);
4327         Cvar_RegisterVariable(&r_glsl_saturation);
4328         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4329         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4330         Cvar_RegisterVariable(&r_framedatasize);
4331         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4332                 Cvar_SetValue("r_fullbrights", 0);
4333         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4334 }
4335
4336 extern void R_Textures_Init(void);
4337 extern void GL_Draw_Init(void);
4338 extern void GL_Main_Init(void);
4339 extern void R_Shadow_Init(void);
4340 extern void R_Sky_Init(void);
4341 extern void GL_Surf_Init(void);
4342 extern void R_Particles_Init(void);
4343 extern void R_Explosion_Init(void);
4344 extern void gl_backend_init(void);
4345 extern void Sbar_Init(void);
4346 extern void R_LightningBeams_Init(void);
4347 extern void Mod_RenderInit(void);
4348 extern void Font_Init(void);
4349
4350 void Render_Init(void)
4351 {
4352         gl_backend_init();
4353         R_Textures_Init();
4354         GL_Main_Init();
4355         Font_Init();
4356         GL_Draw_Init();
4357         R_Shadow_Init();
4358         R_Sky_Init();
4359         GL_Surf_Init();
4360         Sbar_Init();
4361         R_Particles_Init();
4362         R_Explosion_Init();
4363         R_LightningBeams_Init();
4364         Mod_RenderInit();
4365 }
4366
4367 /*
4368 ===============
4369 GL_Init
4370 ===============
4371 */
4372 #ifndef USE_GLES2
4373 extern char *ENGINE_EXTENSIONS;
4374 void GL_Init (void)
4375 {
4376         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4377         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4378         gl_version = (const char *)qglGetString(GL_VERSION);
4379         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4380
4381         if (!gl_extensions)
4382                 gl_extensions = "";
4383         if (!gl_platformextensions)
4384                 gl_platformextensions = "";
4385
4386         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4387         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4388         Con_Printf("GL_VERSION: %s\n", gl_version);
4389         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4390         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4391
4392         VID_CheckExtensions();
4393
4394         // LordHavoc: report supported extensions
4395         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4396
4397         // clear to black (loading plaque will be seen over this)
4398         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4399 }
4400 #endif
4401
4402 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4403 {
4404         int i;
4405         mplane_t *p;
4406         if (r_trippy.integer)
4407                 return false;
4408         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4409         {
4410                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4411                 if (i == 4)
4412                         continue;
4413                 p = r_refdef.view.frustum + i;
4414                 switch(p->signbits)
4415                 {
4416                 default:
4417                 case 0:
4418                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4419                                 return true;
4420                         break;
4421                 case 1:
4422                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 2:
4426                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 3:
4430                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 4:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 5:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 6:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 7:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 }
4450         }
4451         return false;
4452 }
4453
4454 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4455 {
4456         int i;
4457         const mplane_t *p;
4458         if (r_trippy.integer)
4459                 return false;
4460         for (i = 0;i < numplanes;i++)
4461         {
4462                 p = planes + i;
4463                 switch(p->signbits)
4464                 {
4465                 default:
4466                 case 0:
4467                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4468                                 return true;
4469                         break;
4470                 case 1:
4471                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4472                                 return true;
4473                         break;
4474                 case 2:
4475                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4476                                 return true;
4477                         break;
4478                 case 3:
4479                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4480                                 return true;
4481                         break;
4482                 case 4:
4483                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4484                                 return true;
4485                         break;
4486                 case 5:
4487                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4488                                 return true;
4489                         break;
4490                 case 6:
4491                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4492                                 return true;
4493                         break;
4494                 case 7:
4495                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4496                                 return true;
4497                         break;
4498                 }
4499         }
4500         return false;
4501 }
4502
4503 //==================================================================================
4504
4505 // LordHavoc: this stores temporary data used within the same frame
4506
4507 typedef struct r_framedata_mem_s
4508 {
4509         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4510         size_t size; // how much usable space
4511         size_t current; // how much space in use
4512         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4513         size_t wantedsize; // how much space was allocated
4514         unsigned char *data; // start of real data (16byte aligned)
4515 }
4516 r_framedata_mem_t;
4517
4518 static r_framedata_mem_t *r_framedata_mem;
4519
4520 void R_FrameData_Reset(void)
4521 {
4522         while (r_framedata_mem)
4523         {
4524                 r_framedata_mem_t *next = r_framedata_mem->purge;
4525                 Mem_Free(r_framedata_mem);
4526                 r_framedata_mem = next;
4527         }
4528 }
4529
4530 void R_FrameData_Resize(void)
4531 {
4532         size_t wantedsize;
4533         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4534         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4535         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4536         {
4537                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4538                 newmem->wantedsize = wantedsize;
4539                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4540                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4541                 newmem->current = 0;
4542                 newmem->mark = 0;
4543                 newmem->purge = r_framedata_mem;
4544                 r_framedata_mem = newmem;
4545         }
4546 }
4547
4548 void R_FrameData_NewFrame(void)
4549 {
4550         R_FrameData_Resize();
4551         if (!r_framedata_mem)
4552                 return;
4553         // if we ran out of space on the last frame, free the old memory now
4554         while (r_framedata_mem->purge)
4555         {
4556                 // repeatedly remove the second item in the list, leaving only head
4557                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4558                 Mem_Free(r_framedata_mem->purge);
4559                 r_framedata_mem->purge = next;
4560         }
4561         // reset the current mem pointer
4562         r_framedata_mem->current = 0;
4563         r_framedata_mem->mark = 0;
4564 }
4565
4566 void *R_FrameData_Alloc(size_t size)
4567 {
4568         void *data;
4569
4570         // align to 16 byte boundary - the data pointer is already aligned, so we
4571         // only need to ensure the size of every allocation is also aligned
4572         size = (size + 15) & ~15;
4573
4574         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4575         {
4576                 // emergency - we ran out of space, allocate more memory
4577                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4578                 R_FrameData_Resize();
4579         }
4580
4581         data = r_framedata_mem->data + r_framedata_mem->current;
4582         r_framedata_mem->current += size;
4583
4584         // count the usage for stats
4585         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4586         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4587
4588         return (void *)data;
4589 }
4590
4591 void *R_FrameData_Store(size_t size, void *data)
4592 {
4593         void *d = R_FrameData_Alloc(size);
4594         if (d && data)
4595                 memcpy(d, data, size);
4596         return d;
4597 }
4598
4599 void R_FrameData_SetMark(void)
4600 {
4601         if (!r_framedata_mem)
4602                 return;
4603         r_framedata_mem->mark = r_framedata_mem->current;
4604 }
4605
4606 void R_FrameData_ReturnToMark(void)
4607 {
4608         if (!r_framedata_mem)
4609                 return;
4610         r_framedata_mem->current = r_framedata_mem->mark;
4611 }
4612
4613 //==================================================================================
4614
4615 // LordHavoc: animcache originally written by Echon, rewritten since then
4616
4617 /**
4618  * Animation cache prevents re-generating mesh data for an animated model
4619  * multiple times in one frame for lighting, shadowing, reflections, etc.
4620  */
4621
4622 void R_AnimCache_Free(void)
4623 {
4624 }
4625
4626 void R_AnimCache_ClearCache(void)
4627 {
4628         int i;
4629         entity_render_t *ent;
4630
4631         for (i = 0;i < r_refdef.scene.numentities;i++)
4632         {
4633                 ent = r_refdef.scene.entities[i];
4634                 ent->animcache_vertex3f = NULL;
4635                 ent->animcache_normal3f = NULL;
4636                 ent->animcache_svector3f = NULL;
4637                 ent->animcache_tvector3f = NULL;
4638                 ent->animcache_vertexmesh = NULL;
4639                 ent->animcache_vertex3fbuffer = NULL;
4640                 ent->animcache_vertexmeshbuffer = NULL;
4641         }
4642 }
4643
4644 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4645 {
4646         int i;
4647
4648         // check if we need the meshbuffers
4649         if (!vid.useinterleavedarrays)
4650                 return;
4651
4652         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4653                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4654         // TODO: upload vertex3f buffer?
4655         if (ent->animcache_vertexmesh)
4656         {
4657                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4658                 for (i = 0;i < numvertices;i++)
4659                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4660                 if (ent->animcache_svector3f)
4661                         for (i = 0;i < numvertices;i++)
4662                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4663                 if (ent->animcache_tvector3f)
4664                         for (i = 0;i < numvertices;i++)
4665                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4666                 if (ent->animcache_normal3f)
4667                         for (i = 0;i < numvertices;i++)
4668                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4669                 // TODO: upload vertexmeshbuffer?
4670         }
4671 }
4672
4673 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4674 {
4675         dp_model_t *model = ent->model;
4676         int numvertices;
4677         // see if it's already cached this frame
4678         if (ent->animcache_vertex3f)
4679         {
4680                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4681                 if (wantnormals || wanttangents)
4682                 {
4683                         if (ent->animcache_normal3f)
4684                                 wantnormals = false;
4685                         if (ent->animcache_svector3f)
4686                                 wanttangents = false;
4687                         if (wantnormals || wanttangents)
4688                         {
4689                                 numvertices = model->surfmesh.num_vertices;
4690                                 if (wantnormals)
4691                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4692                                 if (wanttangents)
4693                                 {
4694                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4695                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4696                                 }
4697                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4698                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4699                         }
4700                 }
4701         }
4702         else
4703         {
4704                 // see if this ent is worth caching
4705                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4706                         return false;
4707                 // get some memory for this entity and generate mesh data
4708                 numvertices = model->surfmesh.num_vertices;
4709                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4710                 if (wantnormals)
4711                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4712                 if (wanttangents)
4713                 {
4714                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4715                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4716                 }
4717                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4718                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4719         }
4720         return true;
4721 }
4722
4723 void R_AnimCache_CacheVisibleEntities(void)
4724 {
4725         int i;
4726         qboolean wantnormals = true;
4727         qboolean wanttangents = !r_showsurfaces.integer;
4728
4729         switch(vid.renderpath)
4730         {
4731         case RENDERPATH_GL20:
4732         case RENDERPATH_D3D9:
4733         case RENDERPATH_D3D10:
4734         case RENDERPATH_D3D11:
4735         case RENDERPATH_GLES2:
4736                 break;
4737         case RENDERPATH_GL11:
4738         case RENDERPATH_GL13:
4739         case RENDERPATH_GLES1:
4740                 wanttangents = false;
4741                 break;
4742         case RENDERPATH_SOFT:
4743                 break;
4744         }
4745
4746         if (r_shownormals.integer)
4747                 wanttangents = wantnormals = true;
4748
4749         // TODO: thread this
4750         // NOTE: R_PrepareRTLights() also caches entities
4751
4752         for (i = 0;i < r_refdef.scene.numentities;i++)
4753                 if (r_refdef.viewcache.entityvisible[i])
4754                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4755 }
4756
4757 //==================================================================================
4758
4759 extern cvar_t r_overheadsprites_pushback;
4760
4761 static void R_View_UpdateEntityLighting (void)
4762 {
4763         int i;
4764         entity_render_t *ent;
4765         vec3_t tempdiffusenormal, avg;
4766         vec_t f, fa, fd, fdd;
4767         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4768
4769         for (i = 0;i < r_refdef.scene.numentities;i++)
4770         {
4771                 ent = r_refdef.scene.entities[i];
4772
4773                 // skip unseen models and models that updated by CSQC
4774                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4775                         continue;
4776
4777                 // skip bsp models
4778                 if (ent->model && ent->model->brush.num_leafs)
4779                 {
4780                         // TODO: use modellight for r_ambient settings on world?
4781                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4782                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4783                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4784                         continue;
4785                 }
4786
4787                 // fetch the lighting from the worldmodel data
4788                 VectorClear(ent->modellight_ambient);
4789                 VectorClear(ent->modellight_diffuse);
4790                 VectorClear(tempdiffusenormal);
4791                 if (ent->flags & RENDER_LIGHT)
4792                 {
4793                         vec3_t org;
4794                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4795
4796                         // complete lightning for lit sprites
4797                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4798                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4799                         {
4800                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4801                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4802                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4803                         }
4804                         else
4805                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4806
4807                         if(ent->flags & RENDER_EQUALIZE)
4808                         {
4809                                 // first fix up ambient lighting...
4810                                 if(r_equalize_entities_minambient.value > 0)
4811                                 {
4812                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4813                                         if(fd > 0)
4814                                         {
4815                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4816                                                 if(fa < r_equalize_entities_minambient.value * fd)
4817                                                 {
4818                                                         // solve:
4819                                                         //   fa'/fd' = minambient
4820                                                         //   fa'+0.25*fd' = fa+0.25*fd
4821                                                         //   ...
4822                                                         //   fa' = fd' * minambient
4823                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4824                                                         //   ...
4825                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4826                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4827                                                         //   ...
4828                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4829                                                         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
4830                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4831                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4832                                                 }
4833                                         }
4834                                 }
4835
4836                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4837                                 {
4838                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4839                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4840                                         f = fa + 0.25 * fd;
4841                                         if(f > 0)
4842                                         {
4843                                                 // adjust brightness and saturation to target
4844                                                 avg[0] = avg[1] = avg[2] = fa / f;
4845                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4846                                                 avg[0] = avg[1] = avg[2] = fd / f;
4847                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4848                                         }
4849                                 }
4850                         }
4851                 }
4852                 else // highly rare
4853                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4854
4855                 // move the light direction into modelspace coordinates for lighting code
4856                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4857                 if(VectorLength2(ent->modellight_lightdir) == 0)
4858                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4859                 VectorNormalize(ent->modellight_lightdir);
4860         }
4861 }
4862
4863 #define MAX_LINEOFSIGHTTRACES 64
4864
4865 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4866 {
4867         int i;
4868         vec3_t boxmins, boxmaxs;
4869         vec3_t start;
4870         vec3_t end;
4871         dp_model_t *model = r_refdef.scene.worldmodel;
4872
4873         if (!model || !model->brush.TraceLineOfSight)
4874                 return true;
4875
4876         // expand the box a little
4877         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4878         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4879         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4880         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4881         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4882         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4883
4884         // return true if eye is inside enlarged box
4885         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4886                 return true;
4887
4888         // try center
4889         VectorCopy(eye, start);
4890         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4891         if (model->brush.TraceLineOfSight(model, start, end))
4892                 return true;
4893
4894         // try various random positions
4895         for (i = 0;i < numsamples;i++)
4896         {
4897                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4898                 if (model->brush.TraceLineOfSight(model, start, end))
4899                         return true;
4900         }
4901
4902         return false;
4903 }
4904
4905
4906 static void R_View_UpdateEntityVisible (void)
4907 {
4908         int i;
4909         int renderimask;
4910         int samples;
4911         entity_render_t *ent;
4912
4913         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4914                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4915                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4916                 :                                                          RENDER_EXTERIORMODEL;
4917         if (!r_drawviewmodel.integer)
4918                 renderimask |= RENDER_VIEWMODEL;
4919         if (!r_drawexteriormodel.integer)
4920                 renderimask |= RENDER_EXTERIORMODEL;
4921         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4922         {
4923                 // worldmodel can check visibility
4924                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4925                 for (i = 0;i < r_refdef.scene.numentities;i++)
4926                 {
4927                         ent = r_refdef.scene.entities[i];
4928                         if (!(ent->flags & renderimask))
4929                         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)))
4930                         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))
4931                                 r_refdef.viewcache.entityvisible[i] = true;
4932                 }
4933         }
4934         else
4935         {
4936                 // no worldmodel or it can't check visibility
4937                 for (i = 0;i < r_refdef.scene.numentities;i++)
4938                 {
4939                         ent = r_refdef.scene.entities[i];
4940                         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));
4941                 }
4942         }
4943         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4944                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4945         {
4946                 for (i = 0;i < r_refdef.scene.numentities;i++)
4947                 {
4948                         if (!r_refdef.viewcache.entityvisible[i])
4949                                 continue;
4950                         ent = r_refdef.scene.entities[i];
4951                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4952                         {
4953                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4954                                 if (samples < 0)
4955                                         continue; // temp entities do pvs only
4956                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4957                                         ent->last_trace_visibility = realtime;
4958                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4959                                         r_refdef.viewcache.entityvisible[i] = 0;
4960                         }
4961                 }
4962         }
4963 }
4964
4965 /// only used if skyrendermasked, and normally returns false
4966 int R_DrawBrushModelsSky (void)
4967 {
4968         int i, sky;
4969         entity_render_t *ent;
4970
4971         sky = false;
4972         for (i = 0;i < r_refdef.scene.numentities;i++)
4973         {
4974                 if (!r_refdef.viewcache.entityvisible[i])
4975                         continue;
4976                 ent = r_refdef.scene.entities[i];
4977                 if (!ent->model || !ent->model->DrawSky)
4978                         continue;
4979                 ent->model->DrawSky(ent);
4980                 sky = true;
4981         }
4982         return sky;
4983 }
4984
4985 static void R_DrawNoModel(entity_render_t *ent);
4986 static void R_DrawModels(void)
4987 {
4988         int i;
4989         entity_render_t *ent;
4990
4991         for (i = 0;i < r_refdef.scene.numentities;i++)
4992         {
4993                 if (!r_refdef.viewcache.entityvisible[i])
4994                         continue;
4995                 ent = r_refdef.scene.entities[i];
4996                 r_refdef.stats.entities++;
4997                 /*
4998                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4999                 {
5000                         vec3_t f, l, u, o;
5001                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5002                         Con_Printf("R_DrawModels\n");
5003                         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]);
5004                         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);
5005                         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);
5006                 }
5007                 */
5008                 if (ent->model && ent->model->Draw != NULL)
5009                         ent->model->Draw(ent);
5010                 else
5011                         R_DrawNoModel(ent);
5012         }
5013 }
5014
5015 static void R_DrawModelsDepth(void)
5016 {
5017         int i;
5018         entity_render_t *ent;
5019
5020         for (i = 0;i < r_refdef.scene.numentities;i++)
5021         {
5022                 if (!r_refdef.viewcache.entityvisible[i])
5023                         continue;
5024                 ent = r_refdef.scene.entities[i];
5025                 if (ent->model && ent->model->DrawDepth != NULL)
5026                         ent->model->DrawDepth(ent);
5027         }
5028 }
5029
5030 static void R_DrawModelsDebug(void)
5031 {
5032         int i;
5033         entity_render_t *ent;
5034
5035         for (i = 0;i < r_refdef.scene.numentities;i++)
5036         {
5037                 if (!r_refdef.viewcache.entityvisible[i])
5038                         continue;
5039                 ent = r_refdef.scene.entities[i];
5040                 if (ent->model && ent->model->DrawDebug != NULL)
5041                         ent->model->DrawDebug(ent);
5042         }
5043 }
5044
5045 static void R_DrawModelsAddWaterPlanes(void)
5046 {
5047         int i;
5048         entity_render_t *ent;
5049
5050         for (i = 0;i < r_refdef.scene.numentities;i++)
5051         {
5052                 if (!r_refdef.viewcache.entityvisible[i])
5053                         continue;
5054                 ent = r_refdef.scene.entities[i];
5055                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5056                         ent->model->DrawAddWaterPlanes(ent);
5057         }
5058 }
5059
5060 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}};
5061
5062 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5063 {
5064         if (r_hdr_irisadaptation.integer)
5065         {
5066                 vec3_t p;
5067                 vec3_t ambient;
5068                 vec3_t diffuse;
5069                 vec3_t diffusenormal;
5070                 vec3_t forward;
5071                 vec_t brightness = 0.0f;
5072                 vec_t goal;
5073                 vec_t current;
5074                 vec_t d;
5075                 int c;
5076                 VectorCopy(r_refdef.view.forward, forward);
5077                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5078                 {
5079                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5080                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5081                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5082                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5083                         d = DotProduct(forward, diffusenormal);
5084                         brightness += VectorLength(ambient);
5085                         if (d > 0)
5086                                 brightness += d * VectorLength(diffuse);
5087                 }
5088                 brightness *= 1.0f / c;
5089                 brightness += 0.00001f; // make sure it's never zero
5090                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5091                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5092                 current = r_hdr_irisadaptation_value.value;
5093                 if (current < goal)
5094                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5095                 else if (current > goal)
5096                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5097                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5098                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5099         }
5100         else if (r_hdr_irisadaptation_value.value != 1.0f)
5101                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5102 }
5103
5104 static void R_View_SetFrustum(const int *scissor)
5105 {
5106         int i;
5107         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5108         vec3_t forward, left, up, origin, v;
5109
5110         if(scissor)
5111         {
5112                 // flipped x coordinates (because x points left here)
5113                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5114                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5115
5116                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5117                 switch(vid.renderpath)
5118                 {
5119                         case RENDERPATH_D3D9:
5120                         case RENDERPATH_D3D10:
5121                         case RENDERPATH_D3D11:
5122                                 // non-flipped y coordinates
5123                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5124                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5125                                 break;
5126                         case RENDERPATH_SOFT:
5127                         case RENDERPATH_GL11:
5128                         case RENDERPATH_GL13:
5129                         case RENDERPATH_GL20:
5130                         case RENDERPATH_GLES1:
5131                         case RENDERPATH_GLES2:
5132                                 // non-flipped y coordinates
5133                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5134                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5135                                 break;
5136                 }
5137         }
5138
5139         // we can't trust r_refdef.view.forward and friends in reflected scenes
5140         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5141
5142 #if 0
5143         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5144         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5145         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5146         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5147         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5148         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5149         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5150         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5151         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5152         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5153         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5154         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5155 #endif
5156
5157 #if 0
5158         zNear = r_refdef.nearclip;
5159         nudge = 1.0 - 1.0 / (1<<23);
5160         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5161         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5162         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5163         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5164         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5165         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5166         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5167         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5168 #endif
5169
5170
5171
5172 #if 0
5173         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5174         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5175         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5176         r_refdef.view.frustum[0].dist = m[15] - m[12];
5177
5178         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5179         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5180         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5181         r_refdef.view.frustum[1].dist = m[15] + m[12];
5182
5183         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5184         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5185         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5186         r_refdef.view.frustum[2].dist = m[15] - m[13];
5187
5188         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5189         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5190         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5191         r_refdef.view.frustum[3].dist = m[15] + m[13];
5192
5193         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5194         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5195         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5196         r_refdef.view.frustum[4].dist = m[15] - m[14];
5197
5198         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5199         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5200         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5201         r_refdef.view.frustum[5].dist = m[15] + m[14];
5202 #endif
5203
5204         if (r_refdef.view.useperspective)
5205         {
5206                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5207                 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]);
5208                 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]);
5209                 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]);
5210                 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]);
5211
5212                 // then the normals from the corners relative to origin
5213                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5214                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5215                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5216                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5217
5218                 // in a NORMAL view, forward cross left == up
5219                 // in a REFLECTED view, forward cross left == down
5220                 // so our cross products above need to be adjusted for a left handed coordinate system
5221                 CrossProduct(forward, left, v);
5222                 if(DotProduct(v, up) < 0)
5223                 {
5224                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5225                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5226                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5227                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5228                 }
5229
5230                 // Leaving those out was a mistake, those were in the old code, and they
5231                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5232                 // I couldn't reproduce it after adding those normalizations. --blub
5233                 VectorNormalize(r_refdef.view.frustum[0].normal);
5234                 VectorNormalize(r_refdef.view.frustum[1].normal);
5235                 VectorNormalize(r_refdef.view.frustum[2].normal);
5236                 VectorNormalize(r_refdef.view.frustum[3].normal);
5237
5238                 // make the corners absolute
5239                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5240                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5241                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5242                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5243
5244                 // one more normal
5245                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5246
5247                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5248                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5249                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5250                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5251                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5252         }
5253         else
5254         {
5255                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5256                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5257                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5258                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5259                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5260                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5261                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5262                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5263                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5264                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5265         }
5266         r_refdef.view.numfrustumplanes = 5;
5267
5268         if (r_refdef.view.useclipplane)
5269         {
5270                 r_refdef.view.numfrustumplanes = 6;
5271                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5272         }
5273
5274         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5275                 PlaneClassify(r_refdef.view.frustum + i);
5276
5277         // LordHavoc: note to all quake engine coders, Quake had a special case
5278         // for 90 degrees which assumed a square view (wrong), so I removed it,
5279         // Quake2 has it disabled as well.
5280
5281         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5282         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5283         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5284         //PlaneClassify(&frustum[0]);
5285
5286         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5287         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5288         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5289         //PlaneClassify(&frustum[1]);
5290
5291         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5292         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5293         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5294         //PlaneClassify(&frustum[2]);
5295
5296         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5297         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5298         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5299         //PlaneClassify(&frustum[3]);
5300
5301         // nearclip plane
5302         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5303         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5304         //PlaneClassify(&frustum[4]);
5305 }
5306
5307 void R_View_UpdateWithScissor(const int *myscissor)
5308 {
5309         R_Main_ResizeViewCache();
5310         R_View_SetFrustum(myscissor);
5311         R_View_WorldVisibility(r_refdef.view.useclipplane);
5312         R_View_UpdateEntityVisible();
5313         R_View_UpdateEntityLighting();
5314         R_AnimCache_CacheVisibleEntities();
5315 }
5316
5317 void R_View_Update(void)
5318 {
5319         R_Main_ResizeViewCache();
5320         R_View_SetFrustum(NULL);
5321         R_View_WorldVisibility(r_refdef.view.useclipplane);
5322         R_View_UpdateEntityVisible();
5323         R_View_UpdateEntityLighting();
5324         R_AnimCache_CacheVisibleEntities();
5325 }
5326
5327 float viewscalefpsadjusted = 1.0f;
5328
5329 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5330 {
5331         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5332         scale = bound(0.03125f, scale, 1.0f);
5333         *outwidth = (int)ceil(width * scale);
5334         *outheight = (int)ceil(height * scale);
5335 }
5336
5337 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5338 {
5339         const float *customclipplane = NULL;
5340         float plane[4];
5341         int scaledwidth, scaledheight;
5342         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5343         {
5344                 // LordHavoc: couldn't figure out how to make this approach the
5345                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5346                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5347                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5348                         dist = r_refdef.view.clipplane.dist;
5349                 plane[0] = r_refdef.view.clipplane.normal[0];
5350                 plane[1] = r_refdef.view.clipplane.normal[1];
5351                 plane[2] = r_refdef.view.clipplane.normal[2];
5352                 plane[3] = -dist;
5353                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5354         }
5355
5356         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5357         if (!r_refdef.view.useperspective)
5358                 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);
5359         else if (vid.stencil && r_useinfinitefarclip.integer)
5360                 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);
5361         else
5362                 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);
5363         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5364         R_SetViewport(&r_refdef.view.viewport);
5365         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5366         {
5367                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5368                 float screenplane[4];
5369                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5370                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5371                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5372                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5373                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5374         }
5375 }
5376
5377 void R_EntityMatrix(const matrix4x4_t *matrix)
5378 {
5379         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5380         {
5381                 gl_modelmatrixchanged = false;
5382                 gl_modelmatrix = *matrix;
5383                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5384                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5385                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5386                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5387                 CHECKGLERROR
5388                 switch(vid.renderpath)
5389                 {
5390                 case RENDERPATH_D3D9:
5391 #ifdef SUPPORTD3D
5392                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5393                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5394 #endif
5395                         break;
5396                 case RENDERPATH_D3D10:
5397                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5398                         break;
5399                 case RENDERPATH_D3D11:
5400                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5401                         break;
5402                 case RENDERPATH_GL11:
5403                 case RENDERPATH_GL13:
5404                 case RENDERPATH_GLES1:
5405                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5406                         break;
5407                 case RENDERPATH_SOFT:
5408                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5409                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5410                         break;
5411                 case RENDERPATH_GL20:
5412                 case RENDERPATH_GLES2:
5413                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5414                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5415                         break;
5416                 }
5417         }
5418 }
5419
5420 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5421 {
5422         r_viewport_t viewport;
5423         DrawQ_Finish();
5424
5425         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5426         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);
5427         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5428         R_SetViewport(&viewport);
5429         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5430         GL_Color(1, 1, 1, 1);
5431         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5432         GL_BlendFunc(GL_ONE, GL_ZERO);
5433         GL_ScissorTest(false);
5434         GL_DepthMask(false);
5435         GL_DepthRange(0, 1);
5436         GL_DepthTest(false);
5437         GL_DepthFunc(GL_LEQUAL);
5438         R_EntityMatrix(&identitymatrix);
5439         R_Mesh_ResetTextureState();
5440         GL_PolygonOffset(0, 0);
5441         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5442         switch(vid.renderpath)
5443         {
5444         case RENDERPATH_GL11:
5445         case RENDERPATH_GL13:
5446         case RENDERPATH_GL20:
5447         case RENDERPATH_GLES1:
5448         case RENDERPATH_GLES2:
5449                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5450                 break;
5451         case RENDERPATH_D3D9:
5452         case RENDERPATH_D3D10:
5453         case RENDERPATH_D3D11:
5454         case RENDERPATH_SOFT:
5455                 break;
5456         }
5457         GL_CullFace(GL_NONE);
5458 }
5459
5460 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5461 {
5462         DrawQ_Finish();
5463
5464         R_SetupView(true, fbo, depthtexture, colortexture);
5465         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5466         GL_Color(1, 1, 1, 1);
5467         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5468         GL_BlendFunc(GL_ONE, GL_ZERO);
5469         GL_ScissorTest(true);
5470         GL_DepthMask(true);
5471         GL_DepthRange(0, 1);
5472         GL_DepthTest(true);
5473         GL_DepthFunc(GL_LEQUAL);
5474         R_EntityMatrix(&identitymatrix);
5475         R_Mesh_ResetTextureState();
5476         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5477         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5478         switch(vid.renderpath)
5479         {
5480         case RENDERPATH_GL11:
5481         case RENDERPATH_GL13:
5482         case RENDERPATH_GL20:
5483         case RENDERPATH_GLES1:
5484         case RENDERPATH_GLES2:
5485                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5486                 break;
5487         case RENDERPATH_D3D9:
5488         case RENDERPATH_D3D10:
5489         case RENDERPATH_D3D11:
5490         case RENDERPATH_SOFT:
5491                 break;
5492         }
5493         GL_CullFace(r_refdef.view.cullface_back);
5494 }
5495
5496 /*
5497 ================
5498 R_RenderView_UpdateViewVectors
5499 ================
5500 */
5501 static void R_RenderView_UpdateViewVectors(void)
5502 {
5503         // break apart the view matrix into vectors for various purposes
5504         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5505         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5506         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5507         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5508         // make an inverted copy of the view matrix for tracking sprites
5509         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5510 }
5511
5512 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5513 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5514
5515 static void R_Water_StartFrame(void)
5516 {
5517         int i;
5518         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5519         r_waterstate_waterplane_t *p;
5520
5521         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5522                 return;
5523
5524         switch(vid.renderpath)
5525         {
5526         case RENDERPATH_GL20:
5527         case RENDERPATH_D3D9:
5528         case RENDERPATH_D3D10:
5529         case RENDERPATH_D3D11:
5530         case RENDERPATH_SOFT:
5531         case RENDERPATH_GLES2:
5532                 break;
5533         case RENDERPATH_GL11:
5534         case RENDERPATH_GL13:
5535         case RENDERPATH_GLES1:
5536                 return;
5537         }
5538
5539         // set waterwidth and waterheight to the water resolution that will be
5540         // used (often less than the screen resolution for faster rendering)
5541         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5542
5543         // calculate desired texture sizes
5544         // can't use water if the card does not support the texture size
5545         if (!r_water.integer || r_showsurfaces.integer)
5546                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5547         else if (vid.support.arb_texture_non_power_of_two)
5548         {
5549                 texturewidth = waterwidth;
5550                 textureheight = waterheight;
5551                 camerawidth = waterwidth;
5552                 cameraheight = waterheight;
5553         }
5554         else
5555         {
5556                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5557                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5558                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5559                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5560         }
5561
5562         // allocate textures as needed
5563         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight)
5564         {
5565                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5566                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5567                 {
5568                         if (p->texture_refraction)
5569                                 R_FreeTexture(p->texture_refraction);
5570                         p->texture_refraction = NULL;
5571                         if (p->fbo_refraction)
5572                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5573                         p->fbo_refraction = 0;
5574                         if (p->texture_reflection)
5575                                 R_FreeTexture(p->texture_reflection);
5576                         p->texture_reflection = NULL;
5577                         if (p->fbo_reflection)
5578                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5579                         p->fbo_reflection = 0;
5580                         if (p->texture_camera)
5581                                 R_FreeTexture(p->texture_camera);
5582                         p->texture_camera = NULL;
5583                         if (p->fbo_camera)
5584                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5585                         p->fbo_camera = 0;
5586                 }
5587                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5588                 r_fb.water.texturewidth = texturewidth;
5589                 r_fb.water.textureheight = textureheight;
5590                 r_fb.water.camerawidth = camerawidth;
5591                 r_fb.water.cameraheight = cameraheight;
5592         }
5593
5594         if (r_fb.water.texturewidth)
5595         {
5596                 int scaledwidth, scaledheight;
5597
5598                 r_fb.water.enabled = true;
5599
5600                 // water resolution is usually reduced
5601                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5602                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5603                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5604
5605                 // set up variables that will be used in shader setup
5606                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5607                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5608                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5609                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5610         }
5611
5612         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5613         r_fb.water.numwaterplanes = 0;
5614 }
5615
5616 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5617 {
5618         int planeindex, bestplaneindex, vertexindex;
5619         vec3_t mins, maxs, normal, center, v, n;
5620         vec_t planescore, bestplanescore;
5621         mplane_t plane;
5622         r_waterstate_waterplane_t *p;
5623         texture_t *t = R_GetCurrentTexture(surface->texture);
5624
5625         rsurface.texture = t;
5626         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5627         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5628         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5629                 return;
5630         // average the vertex normals, find the surface bounds (after deformvertexes)
5631         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5632         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5633         VectorCopy(n, normal);
5634         VectorCopy(v, mins);
5635         VectorCopy(v, maxs);
5636         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5637         {
5638                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5639                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5640                 VectorAdd(normal, n, normal);
5641                 mins[0] = min(mins[0], v[0]);
5642                 mins[1] = min(mins[1], v[1]);
5643                 mins[2] = min(mins[2], v[2]);
5644                 maxs[0] = max(maxs[0], v[0]);
5645                 maxs[1] = max(maxs[1], v[1]);
5646                 maxs[2] = max(maxs[2], v[2]);
5647         }
5648         VectorNormalize(normal);
5649         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5650
5651         VectorCopy(normal, plane.normal);
5652         VectorNormalize(plane.normal);
5653         plane.dist = DotProduct(center, plane.normal);
5654         PlaneClassify(&plane);
5655         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5656         {
5657                 // skip backfaces (except if nocullface is set)
5658 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5659 //                      return;
5660                 VectorNegate(plane.normal, plane.normal);
5661                 plane.dist *= -1;
5662                 PlaneClassify(&plane);
5663         }
5664
5665
5666         // find a matching plane if there is one
5667         bestplaneindex = -1;
5668         bestplanescore = 1048576.0f;
5669         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5670         {
5671                 if(p->camera_entity == t->camera_entity)
5672                 {
5673                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5674                         if (bestplaneindex < 0 || bestplanescore > planescore)
5675                         {
5676                                 bestplaneindex = planeindex;
5677                                 bestplanescore = planescore;
5678                         }
5679                 }
5680         }
5681         planeindex = bestplaneindex;
5682         p = r_fb.water.waterplanes + planeindex;
5683
5684         // if this surface does not fit any known plane rendered this frame, add one
5685         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5686         {
5687                 // store the new plane
5688                 planeindex = r_fb.water.numwaterplanes++;
5689                 p = r_fb.water.waterplanes + planeindex;
5690                 p->plane = plane;
5691                 // clear materialflags and pvs
5692                 p->materialflags = 0;
5693                 p->pvsvalid = false;
5694                 p->camera_entity = t->camera_entity;
5695                 VectorCopy(mins, p->mins);
5696                 VectorCopy(maxs, p->maxs);
5697         }
5698         else
5699         {
5700                 // merge mins/maxs when we're adding this surface to the plane
5701                 p->mins[0] = min(p->mins[0], mins[0]);
5702                 p->mins[1] = min(p->mins[1], mins[1]);
5703                 p->mins[2] = min(p->mins[2], mins[2]);
5704                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5705                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5706                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5707         }
5708         // merge this surface's materialflags into the waterplane
5709         p->materialflags |= t->currentmaterialflags;
5710         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5711         {
5712                 // merge this surface's PVS into the waterplane
5713                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5714                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5715                 {
5716                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5717                         p->pvsvalid = true;
5718                 }
5719         }
5720 }
5721
5722 extern cvar_t r_drawparticles;
5723 extern cvar_t r_drawdecals;
5724
5725 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5726 {
5727         int myscissor[4];
5728         r_refdef_view_t originalview;
5729         r_refdef_view_t myview;
5730         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;
5731         r_waterstate_waterplane_t *p;
5732         vec3_t visorigin;
5733
5734         originalview = r_refdef.view;
5735
5736         // lowquality hack, temporarily shut down some cvars and restore afterwards
5737         qualityreduction = r_water_lowquality.integer;
5738         if (qualityreduction > 0)
5739         {
5740                 if (qualityreduction >= 1)
5741                 {
5742                         old_r_shadows = r_shadows.integer;
5743                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5744                         old_r_dlight = r_shadow_realtime_dlight.integer;
5745                         Cvar_SetValueQuick(&r_shadows, 0);
5746                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5747                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5748                 }
5749                 if (qualityreduction >= 2)
5750                 {
5751                         old_r_dynamic = r_dynamic.integer;
5752                         old_r_particles = r_drawparticles.integer;
5753                         old_r_decals = r_drawdecals.integer;
5754                         Cvar_SetValueQuick(&r_dynamic, 0);
5755                         Cvar_SetValueQuick(&r_drawparticles, 0);
5756                         Cvar_SetValueQuick(&r_drawdecals, 0);
5757                 }
5758         }
5759
5760         // make sure enough textures are allocated
5761         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5762         {
5763                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5764                 {
5765                         if (!p->texture_refraction)
5766                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5767                         if (!p->texture_refraction)
5768                                 goto error;
5769                         if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5770                         {
5771                                 if (r_fb.water.depthtexture == NULL)
5772                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5773                                 if (p->fbo_refraction == 0)
5774                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5775                         }
5776                 }
5777                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5778                 {
5779                         if (!p->texture_camera)
5780                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_fb.water.camerawidth, r_fb.water.cameraheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5781                         if (!p->texture_camera)
5782                                 goto error;
5783                         if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5784                         {
5785                                 if (r_fb.water.depthtexture == NULL)
5786                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5787                                 if (p->fbo_camera == 0)
5788                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5789                         }
5790                 }
5791
5792                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5793                 {
5794                         if (!p->texture_reflection)
5795                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_fb.water.texturewidth, r_fb.water.textureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5796                         if (!p->texture_reflection)
5797                                 goto error;
5798                         if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5799                         {
5800                                 if (r_fb.water.depthtexture == NULL)
5801                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false);
5802                                 if (p->fbo_reflection == 0)
5803                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5804                         }
5805                 }
5806         }
5807
5808         // render views
5809         r_refdef.view = originalview;
5810         r_refdef.view.showdebug = false;
5811         r_refdef.view.width = r_fb.water.waterwidth;
5812         r_refdef.view.height = r_fb.water.waterheight;
5813         r_refdef.view.useclipplane = true;
5814         myview = r_refdef.view;
5815         r_fb.water.renderingscene = true;
5816         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5817         {
5818                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5819                 {
5820                         r_refdef.view = myview;
5821                         if(r_water_scissormode.integer)
5822                         {
5823                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5824                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5825                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5826                         }
5827
5828                         // render reflected scene and copy into texture
5829                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5830                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5831                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5832                         r_refdef.view.clipplane = p->plane;
5833                         // reverse the cullface settings for this render
5834                         r_refdef.view.cullface_front = GL_FRONT;
5835                         r_refdef.view.cullface_back = GL_BACK;
5836                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5837                         {
5838                                 r_refdef.view.usecustompvs = true;
5839                                 if (p->pvsvalid)
5840                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5841                                 else
5842                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5843                         }
5844
5845                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5846                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5847                         R_ClearScreen(r_refdef.fogenabled);
5848                         if(r_water_scissormode.integer & 2)
5849                                 R_View_UpdateWithScissor(myscissor);
5850                         else
5851                                 R_View_Update();
5852                         if(r_water_scissormode.integer & 1)
5853                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5854                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5855
5856                         if (!p->fbo_reflection)
5857                                 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);
5858                         r_fb.water.hideplayer = false;
5859                 }
5860
5861                 // render the normal view scene and copy into texture
5862                 // (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)
5863                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5864                 {
5865                         r_refdef.view = myview;
5866                         if(r_water_scissormode.integer)
5867                         {
5868                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5869                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5870                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5871                         }
5872
5873                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5874
5875                         r_refdef.view.clipplane = p->plane;
5876                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5877                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5878
5879                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5880                         {
5881                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5882                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5883                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5884                                 R_RenderView_UpdateViewVectors();
5885                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5886                                 {
5887                                         r_refdef.view.usecustompvs = true;
5888                                         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);
5889                                 }
5890                         }
5891
5892                         PlaneClassify(&r_refdef.view.clipplane);
5893
5894                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5895                         R_ClearScreen(r_refdef.fogenabled);
5896                         if(r_water_scissormode.integer & 2)
5897                                 R_View_UpdateWithScissor(myscissor);
5898                         else
5899                                 R_View_Update();
5900                         if(r_water_scissormode.integer & 1)
5901                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5902                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5903
5904                         if (!p->fbo_refraction)
5905                                 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);
5906                         r_fb.water.hideplayer = false;
5907                 }
5908                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5909                 {
5910                         r_refdef.view = myview;
5911
5912                         r_refdef.view.clipplane = p->plane;
5913                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5914                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5915
5916                         r_refdef.view.width = r_fb.water.camerawidth;
5917                         r_refdef.view.height = r_fb.water.cameraheight;
5918                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5919                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5920                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5921                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5922
5923                         if(p->camera_entity)
5924                         {
5925                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5926                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5927                         }
5928
5929                         // note: all of the view is used for displaying... so
5930                         // there is no use in scissoring
5931
5932                         // reverse the cullface settings for this render
5933                         r_refdef.view.cullface_front = GL_FRONT;
5934                         r_refdef.view.cullface_back = GL_BACK;
5935                         // also reverse the view matrix
5936                         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
5937                         R_RenderView_UpdateViewVectors();
5938                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5939                         {
5940                                 r_refdef.view.usecustompvs = true;
5941                                 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);
5942                         }
5943                         
5944                         // camera needs no clipplane
5945                         r_refdef.view.useclipplane = false;
5946
5947                         PlaneClassify(&r_refdef.view.clipplane);
5948
5949                         r_fb.water.hideplayer = false;
5950
5951                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5952                         R_ClearScreen(r_refdef.fogenabled);
5953                         R_View_Update();
5954                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5955
5956                         if (!p->fbo_camera)
5957                                 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);
5958                         r_fb.water.hideplayer = false;
5959                 }
5960
5961         }
5962         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5963         r_fb.water.renderingscene = false;
5964         r_refdef.view = originalview;
5965         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5966         if (!r_fb.water.depthtexture)
5967                 R_ClearScreen(r_refdef.fogenabled);
5968         R_View_Update();
5969         goto finish;
5970 error:
5971         r_refdef.view = originalview;
5972         r_fb.water.renderingscene = false;
5973         Cvar_SetValueQuick(&r_water, 0);
5974         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5975 finish:
5976         // lowquality hack, restore cvars
5977         if (qualityreduction > 0)
5978         {
5979                 if (qualityreduction >= 1)
5980                 {
5981                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5982                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5984                 }
5985                 if (qualityreduction >= 2)
5986                 {
5987                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5988                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5989                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5990                 }
5991         }
5992 }
5993
5994 void R_Bloom_StartFrame(void)
5995 {
5996         int i;
5997         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5998         int viewwidth, viewheight;
5999
6000         r_fb.textype = TEXTYPE_COLORBUFFER;
6001         switch (vid.renderpath)
6002         {
6003         case RENDERPATH_GL20:
6004         case RENDERPATH_GLES2:
6005                 if (vid.support.ext_framebuffer_object)
6006                 {
6007                         if (r_viewfbo.integer == 2) r_fb.textype = TEXTYPE_COLORBUFFER16F;
6008                         if (r_viewfbo.integer == 3) r_fb.textype = TEXTYPE_COLORBUFFER32F;
6009                 }
6010                 break;
6011         case RENDERPATH_GL11:
6012         case RENDERPATH_GL13:
6013         case RENDERPATH_GLES1:
6014         case RENDERPATH_D3D9:
6015         case RENDERPATH_D3D10:
6016         case RENDERPATH_D3D11:
6017         case RENDERPATH_SOFT:
6018                 break;
6019         }
6020
6021         if (r_viewscale_fpsscaling.integer)
6022         {
6023                 double actualframetime;
6024                 double targetframetime;
6025                 double adjust;
6026                 actualframetime = r_refdef.lastdrawscreentime;
6027                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6028                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6029                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6030                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6031                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6032                 viewscalefpsadjusted += adjust;
6033                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6034         }
6035         else
6036                 viewscalefpsadjusted = 1.0f;
6037
6038         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6039
6040         switch(vid.renderpath)
6041         {
6042         case RENDERPATH_GL20:
6043         case RENDERPATH_D3D9:
6044         case RENDERPATH_D3D10:
6045         case RENDERPATH_D3D11:
6046         case RENDERPATH_SOFT:
6047         case RENDERPATH_GLES2:
6048                 break;
6049         case RENDERPATH_GL11:
6050         case RENDERPATH_GL13:
6051         case RENDERPATH_GLES1:
6052                 return;
6053         }
6054
6055         // set bloomwidth and bloomheight to the bloom resolution that will be
6056         // used (often less than the screen resolution for faster rendering)
6057         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6058         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6059         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6060         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6061         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6062
6063         // calculate desired texture sizes
6064         if (vid.support.arb_texture_non_power_of_two)
6065         {
6066                 screentexturewidth = vid.width;
6067                 screentextureheight = vid.height;
6068                 bloomtexturewidth = r_fb.bloomwidth;
6069                 bloomtextureheight = r_fb.bloomheight;
6070         }
6071         else
6072         {
6073                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6074                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6075                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6076                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6077         }
6078
6079         if ((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))
6080         {
6081                 Cvar_SetValueQuick(&r_bloom, 0);
6082                 Cvar_SetValueQuick(&r_motionblur, 0);
6083                 Cvar_SetValueQuick(&r_damageblur, 0);
6084         }
6085
6086         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.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)
6087                 screentexturewidth = screentextureheight = 0;
6088         if (!r_bloom.integer)
6089                 bloomtexturewidth = bloomtextureheight = 0;
6090
6091         // allocate textures as needed
6092         if (r_fb.screentexturewidth != screentexturewidth
6093          || r_fb.screentextureheight != screentextureheight
6094          || r_fb.bloomtexturewidth != bloomtexturewidth
6095          || r_fb.bloomtextureheight != bloomtextureheight
6096          || r_fb.viewfbo != r_viewfbo.integer)
6097         {
6098                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6099                 {
6100                         if (r_fb.bloomtexture[i])
6101                                 R_FreeTexture(r_fb.bloomtexture[i]);
6102                         r_fb.bloomtexture[i] = NULL;
6103
6104                         if (r_fb.bloomfbo[i])
6105                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6106                         r_fb.bloomfbo[i] = 0;
6107                 }
6108
6109                 if (r_fb.fbo)
6110                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6111                 r_fb.fbo = 0;
6112
6113                 if (r_fb.colortexture)
6114                         R_FreeTexture(r_fb.colortexture);
6115                 r_fb.colortexture = NULL;
6116
6117                 if (r_fb.depthtexture)
6118                         R_FreeTexture(r_fb.depthtexture);
6119                 r_fb.depthtexture = NULL;
6120
6121                 if (r_fb.ghosttexture)
6122                         R_FreeTexture(r_fb.ghosttexture);
6123                 r_fb.ghosttexture = NULL;
6124
6125                 r_fb.screentexturewidth = screentexturewidth;
6126                 r_fb.screentextureheight = screentextureheight;
6127                 r_fb.bloomtexturewidth = bloomtexturewidth;
6128                 r_fb.bloomtextureheight = bloomtextureheight;
6129                 r_fb.viewfbo = r_viewfbo.integer;
6130
6131                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6132                 {
6133                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6134                                 r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "framebuffermotionblur", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6135                         r_fb.colortexture = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6136                         if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6137                         {
6138                                 // FIXME: choose depth bits based on a cvar
6139                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false);
6140                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6141                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6142 #ifndef USE_GLES2
6143                                 // render depth into one texture and color into the other
6144                                 if (qglDrawBuffer)
6145                                 {
6146                                         int status;
6147                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6148                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6149                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6150                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6151                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6152                                 }
6153 #endif
6154                         }
6155                 }
6156
6157                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6158                 {
6159                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6160                         {
6161                                 r_fb.bloomtexture[i] = R_LoadTexture2D(r_main_texturepool, "framebufferbloom", r_fb.bloomtexturewidth, r_fb.bloomtextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6162                                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6163                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6164                         }
6165                 }
6166         }
6167
6168         // bloom texture is a different resolution
6169         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6170         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6171         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6172         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6173         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6174
6175         // set up a texcoord array for the full resolution screen image
6176         // (we have to keep this around to copy back during final render)
6177         r_fb.screentexcoord2f[0] = 0;
6178         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6179         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6180         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6181         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6182         r_fb.screentexcoord2f[5] = 0;
6183         r_fb.screentexcoord2f[6] = 0;
6184         r_fb.screentexcoord2f[7] = 0;
6185
6186         // set up a texcoord array for the reduced resolution bloom image
6187         // (which will be additive blended over the screen image)
6188         r_fb.bloomtexcoord2f[0] = 0;
6189         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6190         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6191         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6192         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6193         r_fb.bloomtexcoord2f[5] = 0;
6194         r_fb.bloomtexcoord2f[6] = 0;
6195         r_fb.bloomtexcoord2f[7] = 0;
6196
6197         switch(vid.renderpath)
6198         {
6199         case RENDERPATH_GL11:
6200         case RENDERPATH_GL13:
6201         case RENDERPATH_GL20:
6202         case RENDERPATH_SOFT:
6203         case RENDERPATH_GLES1:
6204         case RENDERPATH_GLES2:
6205                 break;
6206         case RENDERPATH_D3D9:
6207         case RENDERPATH_D3D10:
6208         case RENDERPATH_D3D11:
6209                 {
6210                         int i;
6211                         for (i = 0;i < 4;i++)
6212                         {
6213                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6214                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6215                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6216                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6217                         }
6218                 }
6219                 break;
6220         }
6221
6222         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6223
6224         if (r_fb.fbo)
6225                 r_refdef.view.clear = true;
6226 }
6227
6228 void R_Bloom_MakeTexture(void)
6229 {
6230         int x, range, dir;
6231         float xoffset, yoffset, r, brighten;
6232         rtexture_t *intex;
6233         float colorscale = r_bloom_colorscale.value;
6234
6235         r_refdef.stats.bloom++;
6236
6237         if (!r_fb.fbo)
6238         {
6239                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6240                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6241         }
6242
6243         // scale down screen texture to the bloom texture size
6244         CHECKGLERROR
6245         r_fb.bloomindex = 0;
6246         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6247         R_SetViewport(&r_fb.bloomviewport);
6248         GL_BlendFunc(GL_ONE, GL_ZERO);
6249         GL_Color(colorscale, colorscale, colorscale, 1);
6250         // 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...
6251         switch(vid.renderpath)
6252         {
6253         case RENDERPATH_GL11:
6254         case RENDERPATH_GL13:
6255         case RENDERPATH_GL20:
6256         case RENDERPATH_GLES1:
6257         case RENDERPATH_GLES2:
6258         case RENDERPATH_SOFT:
6259                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6260                 break;
6261         case RENDERPATH_D3D9:
6262         case RENDERPATH_D3D10:
6263         case RENDERPATH_D3D11:
6264                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6265                 break;
6266         }
6267         // TODO: do boxfilter scale-down in shader?
6268         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true);
6269         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6270         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6271
6272         // we now have a properly scaled bloom image
6273         if (!r_fb.bloomfbo[r_fb.bloomindex])
6274         {
6275                 // copy it into the bloom texture
6276                 R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6277                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6278         }
6279
6280         // multiply bloom image by itself as many times as desired
6281         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6282         {
6283                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6284                 r_fb.bloomindex ^= 1;
6285                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6286                 x *= 2;
6287                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6288                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6289                 GL_Color(r,r,r,1);
6290                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6291                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true);
6292                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6293                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6294
6295                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6296                 {
6297                         // copy the darkened image to a texture
6298                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6299                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6300                 }
6301         }
6302
6303         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6304         brighten = r_bloom_brighten.value;
6305         brighten = sqrt(brighten);
6306         if(range >= 1)
6307                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6308
6309         for (dir = 0;dir < 2;dir++)
6310         {
6311                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6312                 r_fb.bloomindex ^= 1;
6313                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6314                 // blend on at multiple vertical offsets to achieve a vertical blur
6315                 // TODO: do offset blends using GLSL
6316                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6317                 GL_BlendFunc(GL_ONE, GL_ZERO);
6318                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true);
6319                 for (x = -range;x <= range;x++)
6320                 {
6321                         if (!dir){xoffset = 0;yoffset = x;}
6322                         else {xoffset = x;yoffset = 0;}
6323                         xoffset /= (float)r_fb.bloomtexturewidth;
6324                         yoffset /= (float)r_fb.bloomtextureheight;
6325                         // compute a texcoord array with the specified x and y offset
6326                         r_fb.offsettexcoord2f[0] = xoffset+0;
6327                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6328                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6329                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6330                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6331                         r_fb.offsettexcoord2f[5] = yoffset+0;
6332                         r_fb.offsettexcoord2f[6] = xoffset+0;
6333                         r_fb.offsettexcoord2f[7] = yoffset+0;
6334                         // this r value looks like a 'dot' particle, fading sharply to
6335                         // black at the edges
6336                         // (probably not realistic but looks good enough)
6337                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6338                         //r = brighten/(range*2+1);
6339                         r = brighten / (range * 2 + 1);
6340                         if(range >= 1)
6341                                 r *= (1 - x*x/(float)(range*range));
6342                         GL_Color(r, r, r, 1);
6343                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6344                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6345                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6346                         GL_BlendFunc(GL_ONE, GL_ONE);
6347                 }
6348
6349                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6350                 {
6351                         // copy the vertically or horizontally blurred bloom view to a texture
6352                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6353                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6354                 }
6355         }
6356 }
6357
6358 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6359 {
6360         unsigned int permutation;
6361         float uservecs[4][4];
6362
6363         switch (vid.renderpath)
6364         {
6365         case RENDERPATH_GL20:
6366         case RENDERPATH_D3D9:
6367         case RENDERPATH_D3D10:
6368         case RENDERPATH_D3D11:
6369         case RENDERPATH_SOFT:
6370         case RENDERPATH_GLES2:
6371                 permutation =
6372                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6373                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6374                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6375                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6376                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6377
6378                 if (r_fb.colortexture)
6379                 {
6380                         if (!r_fb.fbo)
6381                         {
6382                                 R_Mesh_CopyToTexture(r_fb.colortexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6383                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6384                         }
6385
6386                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6387                         {
6388                                 // declare variables
6389                                 float blur_factor, blur_mouseaccel, blur_velocity;
6390                                 static float blur_average; 
6391                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6392
6393                                 // set a goal for the factoring
6394                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6395                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6396                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6397                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6398                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6399                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6400
6401                                 // from the goal, pick an averaged value between goal and last value
6402                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6403                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6404
6405                                 // enforce minimum amount of blur 
6406                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6407
6408                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6409
6410                                 // calculate values into a standard alpha
6411                                 cl.motionbluralpha = 1 - exp(-
6412                                                 (
6413                                                  (r_motionblur.value * blur_factor / 80)
6414                                                  +
6415                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6416                                                 )
6417                                                 /
6418                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6419                                           );
6420
6421                                 // randomization for the blur value to combat persistent ghosting
6422                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6423                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6424
6425                                 // apply the blur
6426                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6427                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture)
6428                                 {
6429                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6430                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6431                                         switch(vid.renderpath)
6432                                         {
6433                                         case RENDERPATH_GL11:
6434                                         case RENDERPATH_GL13:
6435                                         case RENDERPATH_GL20:
6436                                         case RENDERPATH_GLES1:
6437                                         case RENDERPATH_GLES2:
6438                                         case RENDERPATH_SOFT:
6439                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6440                                                 break;
6441                                         case RENDERPATH_D3D9:
6442                                         case RENDERPATH_D3D10:
6443                                         case RENDERPATH_D3D11:
6444                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6445                                                 break;
6446                                         }
6447                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true);
6448                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6449                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6450                                 }
6451
6452                                 // updates old view angles for next pass
6453                                 VectorCopy(cl.viewangles, blur_oldangles);
6454
6455                                 // copy view into the ghost texture
6456                                 if (!r_fb.ghosttexture)
6457                                         r_fb.ghosttexture = R_LoadTexture2D(r_main_texturepool, "motionblurtexture", r_fb.screentexturewidth, r_fb.screentextureheight, NULL, r_fb.textype, TEXF_RENDERTARGET | TEXF_FORCENEAREST | TEXF_CLAMP, -1, NULL);
6458                                 R_Mesh_CopyToTexture(r_fb.ghosttexture, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6459                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6460                         }
6461                 }
6462                 else
6463                 {
6464                         // no r_fb.colortexture means we're rendering to the real fb
6465                         // we may still have to do view tint...
6466                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6467                         {
6468                                 // apply a color tint to the whole view
6469                                 R_ResetViewRendering2D(0, NULL, NULL);
6470                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6471                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6472                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6473                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6474                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6475                         }
6476                         break; // no screen processing, no bloom, skip it
6477                 }
6478
6479                 if (r_fb.bloomtexture[0])
6480                 {
6481                         // make the bloom texture
6482                         R_Bloom_MakeTexture();
6483                 }
6484
6485 #if _MSC_VER >= 1400
6486 #define sscanf sscanf_s
6487 #endif
6488                 memset(uservecs, 0, sizeof(uservecs));
6489                 if (r_glsl_postprocess_uservec1_enable.integer)
6490                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6491                 if (r_glsl_postprocess_uservec2_enable.integer)
6492                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6493                 if (r_glsl_postprocess_uservec3_enable.integer)
6494                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6495                 if (r_glsl_postprocess_uservec4_enable.integer)
6496                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6497
6498                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6499                 GL_Color(1, 1, 1, 1);
6500                 GL_BlendFunc(GL_ONE, GL_ZERO);
6501
6502                 switch(vid.renderpath)
6503                 {
6504                 case RENDERPATH_GL20:
6505                 case RENDERPATH_GLES2:
6506                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6507                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6508                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6509                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6510                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6511                         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]);
6512                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6513                         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]);
6514                         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]);
6515                         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]);
6516                         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]);
6517                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6518                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6519                         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);
6520                         break;
6521                 case RENDERPATH_D3D9:
6522 #ifdef SUPPORTD3D
6523                         // 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...
6524                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6525                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6526                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6527                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture);
6528                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6529                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6530                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6531                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6532                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6533                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6534                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6535                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6536                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6537                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6538 #endif
6539                         break;
6540                 case RENDERPATH_D3D10:
6541                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6542                         break;
6543                 case RENDERPATH_D3D11:
6544                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6545                         break;
6546                 case RENDERPATH_SOFT:
6547                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6548                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6549                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6550                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6551                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6552                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6553                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6554                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6555                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6556                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6557                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6558                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6559                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6560                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6561                         break;
6562                 default:
6563                         break;
6564                 }
6565                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6566                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6567                 break;
6568         case RENDERPATH_GL11:
6569         case RENDERPATH_GL13:
6570         case RENDERPATH_GLES1:
6571                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6572                 {
6573                         // apply a color tint to the whole view
6574                         R_ResetViewRendering2D(0, NULL, NULL);
6575                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6576                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6577                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6578                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6579                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6580                 }
6581                 break;
6582         }
6583 }
6584
6585 matrix4x4_t r_waterscrollmatrix;
6586
6587 void R_UpdateFog(void)
6588 {
6589         // Nehahra fog
6590         if (gamemode == GAME_NEHAHRA)
6591         {
6592                 if (gl_fogenable.integer)
6593                 {
6594                         r_refdef.oldgl_fogenable = true;
6595                         r_refdef.fog_density = gl_fogdensity.value;
6596                         r_refdef.fog_red = gl_fogred.value;
6597                         r_refdef.fog_green = gl_foggreen.value;
6598                         r_refdef.fog_blue = gl_fogblue.value;
6599                         r_refdef.fog_alpha = 1;
6600                         r_refdef.fog_start = 0;
6601                         r_refdef.fog_end = gl_skyclip.value;
6602                         r_refdef.fog_height = 1<<30;
6603                         r_refdef.fog_fadedepth = 128;
6604                 }
6605                 else if (r_refdef.oldgl_fogenable)
6606                 {
6607                         r_refdef.oldgl_fogenable = false;
6608                         r_refdef.fog_density = 0;
6609                         r_refdef.fog_red = 0;
6610                         r_refdef.fog_green = 0;
6611                         r_refdef.fog_blue = 0;
6612                         r_refdef.fog_alpha = 0;
6613                         r_refdef.fog_start = 0;
6614                         r_refdef.fog_end = 0;
6615                         r_refdef.fog_height = 1<<30;
6616                         r_refdef.fog_fadedepth = 128;
6617                 }
6618         }
6619
6620         // fog parms
6621         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6622         r_refdef.fog_start = max(0, r_refdef.fog_start);
6623         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6624
6625         if (r_refdef.fog_density && r_drawfog.integer)
6626         {
6627                 r_refdef.fogenabled = true;
6628                 // this is the point where the fog reaches 0.9986 alpha, which we
6629                 // consider a good enough cutoff point for the texture
6630                 // (0.9986 * 256 == 255.6)
6631                 if (r_fog_exp2.integer)
6632                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6633                 else
6634                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6635                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6636                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6637                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6638                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6639                         R_BuildFogHeightTexture();
6640                 // fog color was already set
6641                 // update the fog texture
6642                 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)
6643                         R_BuildFogTexture();
6644                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6645                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6646         }
6647         else
6648                 r_refdef.fogenabled = false;
6649
6650         // fog color
6651         if (r_refdef.fog_density)
6652         {
6653                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6654                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6655                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6656
6657                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6658                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6659                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6660                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6661
6662                 {
6663                         vec3_t fogvec;
6664                         VectorCopy(r_refdef.fogcolor, fogvec);
6665                         //   color.rgb *= ContrastBoost * SceneBrightness;
6666                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6667                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6668                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6669                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6670                 }
6671         }
6672 }
6673
6674 void R_UpdateVariables(void)
6675 {
6676         R_Textures_Frame();
6677
6678         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6679
6680         r_refdef.farclip = r_farclip_base.value;
6681         if (r_refdef.scene.worldmodel)
6682                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6683         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6684
6685         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6686                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6687         r_refdef.polygonfactor = 0;
6688         r_refdef.polygonoffset = 0;
6689         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6690         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6691
6692         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6693         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6694         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6695         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6696         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6697         if (FAKELIGHT_ENABLED)
6698         {
6699                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6700         }
6701         if (r_showsurfaces.integer)
6702         {
6703                 r_refdef.scene.rtworld = false;
6704                 r_refdef.scene.rtworldshadows = false;
6705                 r_refdef.scene.rtdlight = false;
6706                 r_refdef.scene.rtdlightshadows = false;
6707                 r_refdef.lightmapintensity = 0;
6708         }
6709
6710         switch(vid.renderpath)
6711         {
6712         case RENDERPATH_GL20:
6713         case RENDERPATH_D3D9:
6714         case RENDERPATH_D3D10:
6715         case RENDERPATH_D3D11:
6716         case RENDERPATH_SOFT:
6717         case RENDERPATH_GLES2:
6718                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6719                 {
6720                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6721                         {
6722                                 // build GLSL gamma texture
6723 #define RAMPWIDTH 256
6724                                 unsigned short ramp[RAMPWIDTH * 3];
6725                                 unsigned char rampbgr[RAMPWIDTH][4];
6726                                 int i;
6727
6728                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6729
6730                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6731                                 for(i = 0; i < RAMPWIDTH; ++i)
6732                                 {
6733                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6734                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6735                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6736                                         rampbgr[i][3] = 0;
6737                                 }
6738                                 if (r_texture_gammaramps)
6739                                 {
6740                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6741                                 }
6742                                 else
6743                                 {
6744                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6745                                 }
6746                         }
6747                 }
6748                 else
6749                 {
6750                         // remove GLSL gamma texture
6751                 }
6752                 break;
6753         case RENDERPATH_GL11:
6754         case RENDERPATH_GL13:
6755         case RENDERPATH_GLES1:
6756                 break;
6757         }
6758 }
6759
6760 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6761 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6762 /*
6763 ================
6764 R_SelectScene
6765 ================
6766 */
6767 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6768         if( scenetype != r_currentscenetype ) {
6769                 // store the old scenetype
6770                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6771                 r_currentscenetype = scenetype;
6772                 // move in the new scene
6773                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6774         }
6775 }
6776
6777 /*
6778 ================
6779 R_GetScenePointer
6780 ================
6781 */
6782 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6783 {
6784         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6785         if( scenetype == r_currentscenetype ) {
6786                 return &r_refdef.scene;
6787         } else {
6788                 return &r_scenes_store[ scenetype ];
6789         }
6790 }
6791
6792 int R_SortEntities_Compare(const void *ap, const void *bp)
6793 {
6794         const entity_render_t *a = *(const entity_render_t **)ap;
6795         const entity_render_t *b = *(const entity_render_t **)bp;
6796
6797         // 1. compare model
6798         if(a->model < b->model)
6799                 return -1;
6800         if(a->model > b->model)
6801                 return +1;
6802
6803         // 2. compare skin
6804         // TODO possibly calculate the REAL skinnum here first using
6805         // skinscenes?
6806         if(a->skinnum < b->skinnum)
6807                 return -1;
6808         if(a->skinnum > b->skinnum)
6809                 return +1;
6810
6811         // everything we compared is equal
6812         return 0;
6813 }
6814 void R_SortEntities(void)
6815 {
6816         // below or equal 2 ents, sorting never gains anything
6817         if(r_refdef.scene.numentities <= 2)
6818                 return;
6819         // sort
6820         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6821 }
6822
6823 /*
6824 ================
6825 R_RenderView
6826 ================
6827 */
6828 int dpsoftrast_test;
6829 extern void R_Shadow_UpdateBounceGridTexture(void);
6830 extern cvar_t r_shadow_bouncegrid;
6831 void R_RenderView(void)
6832 {
6833         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6834         int fbo;
6835         rtexture_t *depthtexture;
6836         rtexture_t *colortexture;
6837
6838         dpsoftrast_test = r_test.integer;
6839
6840         if (r_timereport_active)
6841                 R_TimeReport("start");
6842         r_textureframe++; // used only by R_GetCurrentTexture
6843         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6844
6845         if(R_CompileShader_CheckStaticParms())
6846                 R_GLSL_Restart_f();
6847
6848         if (!r_drawentities.integer)
6849                 r_refdef.scene.numentities = 0;
6850         else if (r_sortentities.integer)
6851                 R_SortEntities();
6852
6853         R_AnimCache_ClearCache();
6854         R_FrameData_NewFrame();
6855
6856         /* adjust for stereo display */
6857         if(R_Stereo_Active())
6858         {
6859                 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);
6860                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6861         }
6862
6863         if (r_refdef.view.isoverlay)
6864         {
6865                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6866                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6867                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6868                 R_TimeReport("depthclear");
6869
6870                 r_refdef.view.showdebug = false;
6871
6872                 r_fb.water.enabled = false;
6873                 r_fb.water.numwaterplanes = 0;
6874
6875                 R_RenderScene(0, NULL, NULL);
6876
6877                 r_refdef.view.matrix = originalmatrix;
6878
6879                 CHECKGLERROR
6880                 return;
6881         }
6882
6883         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6884         {
6885                 r_refdef.view.matrix = originalmatrix;
6886                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6887         }
6888
6889         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6890
6891         R_RenderView_UpdateViewVectors();
6892
6893         R_Shadow_UpdateWorldLightSelection();
6894
6895         R_Bloom_StartFrame();
6896         R_Water_StartFrame();
6897
6898         // now we probably have an fbo to render into
6899         fbo = r_fb.fbo;
6900         depthtexture = r_fb.depthtexture;
6901         colortexture = r_fb.colortexture;
6902
6903         CHECKGLERROR
6904         if (r_timereport_active)
6905                 R_TimeReport("viewsetup");
6906
6907         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6908
6909         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6910         {
6911                 R_ClearScreen(r_refdef.fogenabled);
6912                 if (r_timereport_active)
6913                         R_TimeReport("viewclear");
6914         }
6915         r_refdef.view.clear = true;
6916
6917         r_refdef.view.showdebug = true;
6918
6919         R_View_Update();
6920         if (r_timereport_active)
6921                 R_TimeReport("visibility");
6922
6923         R_Shadow_UpdateBounceGridTexture();
6924         if (r_timereport_active && r_shadow_bouncegrid.integer)
6925                 R_TimeReport("bouncegrid");
6926
6927         r_fb.water.numwaterplanes = 0;
6928         if (r_fb.water.enabled)
6929                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6930
6931         R_RenderScene(fbo, depthtexture, colortexture);
6932         r_fb.water.numwaterplanes = 0;
6933
6934         R_BlendView(fbo, depthtexture, colortexture);
6935         if (r_timereport_active)
6936                 R_TimeReport("blendview");
6937
6938         GL_Scissor(0, 0, vid.width, vid.height);
6939         GL_ScissorTest(false);
6940
6941         r_refdef.view.matrix = originalmatrix;
6942
6943         CHECKGLERROR
6944 }
6945
6946 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6947 {
6948         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6949         {
6950                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6951                 if (r_timereport_active)
6952                         R_TimeReport("waterworld");
6953         }
6954
6955         // don't let sound skip if going slow
6956         if (r_refdef.scene.extraupdate)
6957                 S_ExtraUpdate ();
6958
6959         R_DrawModelsAddWaterPlanes();
6960         if (r_timereport_active)
6961                 R_TimeReport("watermodels");
6962
6963         if (r_fb.water.numwaterplanes)
6964         {
6965                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6966                 if (r_timereport_active)
6967                         R_TimeReport("waterscenes");
6968         }
6969 }
6970
6971 extern void R_DrawLightningBeams (void);
6972 extern void VM_CL_AddPolygonsToMeshQueue (void);
6973 extern void R_DrawPortals (void);
6974 extern cvar_t cl_locs_show;
6975 static void R_DrawLocs(void);
6976 static void R_DrawEntityBBoxes(void);
6977 static void R_DrawModelDecals(void);
6978 extern void R_DrawModelShadows(void);
6979 extern void R_DrawModelShadowMaps(void);
6980 extern cvar_t cl_decals_newsystem;
6981 extern qboolean r_shadow_usingdeferredprepass;
6982 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6983 {
6984         qboolean shadowmapping = false;
6985
6986         if (r_timereport_active)
6987                 R_TimeReport("beginscene");
6988
6989         r_refdef.stats.renders++;
6990
6991         R_UpdateFog();
6992
6993         // don't let sound skip if going slow
6994         if (r_refdef.scene.extraupdate)
6995                 S_ExtraUpdate ();
6996
6997         R_MeshQueue_BeginScene();
6998
6999         R_SkyStartFrame();
7000
7001         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);
7002
7003         if (r_timereport_active)
7004                 R_TimeReport("skystartframe");
7005
7006         if (cl.csqc_vidvars.drawworld)
7007         {
7008                 // don't let sound skip if going slow
7009                 if (r_refdef.scene.extraupdate)
7010                         S_ExtraUpdate ();
7011
7012                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7013                 {
7014                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7015                         if (r_timereport_active)
7016                                 R_TimeReport("worldsky");
7017                 }
7018
7019                 if (R_DrawBrushModelsSky() && r_timereport_active)
7020                         R_TimeReport("bmodelsky");
7021
7022                 if (skyrendermasked && skyrenderlater)
7023                 {
7024                         // we have to force off the water clipping plane while rendering sky
7025                         R_SetupView(false, fbo, depthtexture, colortexture);
7026                         R_Sky();
7027                         R_SetupView(true, fbo, depthtexture, colortexture);
7028                         if (r_timereport_active)
7029                                 R_TimeReport("sky");
7030                 }
7031         }
7032
7033         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7034         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7035                 R_Shadow_PrepareModelShadows();
7036         if (r_timereport_active)
7037                 R_TimeReport("preparelights");
7038
7039         if (R_Shadow_ShadowMappingEnabled())
7040                 shadowmapping = true;
7041
7042         if (r_shadow_usingdeferredprepass)
7043                 R_Shadow_DrawPrepass();
7044
7045         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7046         {
7047                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7048                 if (r_timereport_active)
7049                         R_TimeReport("worlddepth");
7050         }
7051         if (r_depthfirst.integer >= 2)
7052         {
7053                 R_DrawModelsDepth();
7054                 if (r_timereport_active)
7055                         R_TimeReport("modeldepth");
7056         }
7057
7058         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7059         {
7060                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7061                 R_DrawModelShadowMaps();
7062                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7063                 // don't let sound skip if going slow
7064                 if (r_refdef.scene.extraupdate)
7065                         S_ExtraUpdate ();
7066         }
7067
7068         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7069         {
7070                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7071                 if (r_timereport_active)
7072                         R_TimeReport("world");
7073         }
7074
7075         // don't let sound skip if going slow
7076         if (r_refdef.scene.extraupdate)
7077                 S_ExtraUpdate ();
7078
7079         R_DrawModels();
7080         if (r_timereport_active)
7081                 R_TimeReport("models");
7082
7083         // don't let sound skip if going slow
7084         if (r_refdef.scene.extraupdate)
7085                 S_ExtraUpdate ();
7086
7087         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7088         {
7089                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7090                 R_DrawModelShadows();
7091                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7092                 // don't let sound skip if going slow
7093                 if (r_refdef.scene.extraupdate)
7094                         S_ExtraUpdate ();
7095         }
7096
7097         if (!r_shadow_usingdeferredprepass)
7098         {
7099                 R_Shadow_DrawLights();
7100                 if (r_timereport_active)
7101                         R_TimeReport("rtlights");
7102         }
7103
7104         // don't let sound skip if going slow
7105         if (r_refdef.scene.extraupdate)
7106                 S_ExtraUpdate ();
7107
7108         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7109         {
7110                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7111                 R_DrawModelShadows();
7112                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7113                 // don't let sound skip if going slow
7114                 if (r_refdef.scene.extraupdate)
7115                         S_ExtraUpdate ();
7116         }
7117
7118         if (cl.csqc_vidvars.drawworld)
7119         {
7120                 if (cl_decals_newsystem.integer)
7121                 {
7122                         R_DrawModelDecals();
7123                         if (r_timereport_active)
7124                                 R_TimeReport("modeldecals");
7125                 }
7126                 else
7127                 {
7128                         R_DrawDecals();
7129                         if (r_timereport_active)
7130                                 R_TimeReport("decals");
7131                 }
7132
7133                 R_DrawParticles();
7134                 if (r_timereport_active)
7135                         R_TimeReport("particles");
7136
7137                 R_DrawExplosions();
7138                 if (r_timereport_active)
7139                         R_TimeReport("explosions");
7140
7141                 R_DrawLightningBeams();
7142                 if (r_timereport_active)
7143                         R_TimeReport("lightning");
7144         }
7145
7146         VM_CL_AddPolygonsToMeshQueue();
7147
7148         if (r_refdef.view.showdebug)
7149         {
7150                 if (cl_locs_show.integer)
7151                 {
7152                         R_DrawLocs();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("showlocs");
7155                 }
7156
7157                 if (r_drawportals.integer)
7158                 {
7159                         R_DrawPortals();
7160                         if (r_timereport_active)
7161                                 R_TimeReport("portals");
7162                 }
7163
7164                 if (r_showbboxes.value > 0)
7165                 {
7166                         R_DrawEntityBBoxes();
7167                         if (r_timereport_active)
7168                                 R_TimeReport("bboxes");
7169                 }
7170         }
7171
7172         if (r_transparent.integer)
7173         {
7174                 R_MeshQueue_RenderTransparent();
7175                 if (r_timereport_active)
7176                         R_TimeReport("drawtrans");
7177         }
7178
7179         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))
7180         {
7181                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7182                 if (r_timereport_active)
7183                         R_TimeReport("worlddebug");
7184                 R_DrawModelsDebug();
7185                 if (r_timereport_active)
7186                         R_TimeReport("modeldebug");
7187         }
7188
7189         if (cl.csqc_vidvars.drawworld)
7190         {
7191                 R_Shadow_DrawCoronas();
7192                 if (r_timereport_active)
7193                         R_TimeReport("coronas");
7194         }
7195
7196 #if 0
7197         {
7198                 GL_DepthTest(false);
7199                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7200                 GL_Color(1, 1, 1, 1);
7201                 qglBegin(GL_POLYGON);
7202                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7203                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7204                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7205                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7206                 qglEnd();
7207                 qglBegin(GL_POLYGON);
7208                 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]);
7209                 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]);
7210                 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]);
7211                 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]);
7212                 qglEnd();
7213                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7214         }
7215 #endif
7216
7217         // don't let sound skip if going slow
7218         if (r_refdef.scene.extraupdate)
7219                 S_ExtraUpdate ();
7220 }
7221
7222 static const unsigned short bboxelements[36] =
7223 {
7224         5, 1, 3, 5, 3, 7,
7225         6, 2, 0, 6, 0, 4,
7226         7, 3, 2, 7, 2, 6,
7227         4, 0, 1, 4, 1, 5,
7228         4, 5, 7, 4, 7, 6,
7229         1, 0, 2, 1, 2, 3,
7230 };
7231
7232 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7233 {
7234         int i;
7235         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7236
7237         RSurf_ActiveWorldEntity();
7238
7239         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7240         GL_DepthMask(false);
7241         GL_DepthRange(0, 1);
7242         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7243 //      R_Mesh_ResetTextureState();
7244
7245         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7246         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7247         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7248         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7249         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7250         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7251         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7252         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7253         R_FillColors(color4f, 8, cr, cg, cb, ca);
7254         if (r_refdef.fogenabled)
7255         {
7256                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7257                 {
7258                         f1 = RSurf_FogVertex(v);
7259                         f2 = 1 - f1;
7260                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7261                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7262                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7263                 }
7264         }
7265         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7266         R_Mesh_ResetTextureState();
7267         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7268         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7269 }
7270
7271 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7272 {
7273         int i;
7274         float color[4];
7275         prvm_edict_t *edict;
7276         prvm_prog_t *prog_save = prog;
7277
7278         // this function draws bounding boxes of server entities
7279         if (!sv.active)
7280                 return;
7281
7282         GL_CullFace(GL_NONE);
7283         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7284
7285         prog = 0;
7286         SV_VM_Begin();
7287         for (i = 0;i < numsurfaces;i++)
7288         {
7289                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7290                 switch ((int)PRVM_serveredictfloat(edict, solid))
7291                 {
7292                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7293                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7294                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7295                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7296                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7297                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7298                 }
7299                 color[3] *= r_showbboxes.value;
7300                 color[3] = bound(0, color[3], 1);
7301                 GL_DepthTest(!r_showdisabledepthtest.integer);
7302                 GL_CullFace(r_refdef.view.cullface_front);
7303                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7304         }
7305         SV_VM_End();
7306         prog = prog_save;
7307 }
7308
7309 static void R_DrawEntityBBoxes(void)
7310 {
7311         int i;
7312         prvm_edict_t *edict;
7313         vec3_t center;
7314         prvm_prog_t *prog_save = prog;
7315
7316         // this function draws bounding boxes of server entities
7317         if (!sv.active)
7318                 return;
7319
7320         prog = 0;
7321         SV_VM_Begin();
7322         for (i = 0;i < prog->num_edicts;i++)
7323         {
7324                 edict = PRVM_EDICT_NUM(i);
7325                 if (edict->priv.server->free)
7326                         continue;
7327                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7328                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7329                         continue;
7330                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7331                         continue;
7332                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7333                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7334         }
7335         SV_VM_End();
7336         prog = prog_save;
7337 }
7338
7339 static const int nomodelelement3i[24] =
7340 {
7341         5, 2, 0,
7342         5, 1, 2,
7343         5, 0, 3,
7344         5, 3, 1,
7345         0, 2, 4,
7346         2, 1, 4,
7347         3, 0, 4,
7348         1, 3, 4
7349 };
7350
7351 static const unsigned short nomodelelement3s[24] =
7352 {
7353         5, 2, 0,
7354         5, 1, 2,
7355         5, 0, 3,
7356         5, 3, 1,
7357         0, 2, 4,
7358         2, 1, 4,
7359         3, 0, 4,
7360         1, 3, 4
7361 };
7362
7363 static const float nomodelvertex3f[6*3] =
7364 {
7365         -16,   0,   0,
7366          16,   0,   0,
7367           0, -16,   0,
7368           0,  16,   0,
7369           0,   0, -16,
7370           0,   0,  16
7371 };
7372
7373 static const float nomodelcolor4f[6*4] =
7374 {
7375         0.0f, 0.0f, 0.5f, 1.0f,
7376         0.0f, 0.0f, 0.5f, 1.0f,
7377         0.0f, 0.5f, 0.0f, 1.0f,
7378         0.0f, 0.5f, 0.0f, 1.0f,
7379         0.5f, 0.0f, 0.0f, 1.0f,
7380         0.5f, 0.0f, 0.0f, 1.0f
7381 };
7382
7383 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7384 {
7385         int i;
7386         float f1, f2, *c;
7387         float color4f[6*4];
7388
7389         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);
7390
7391         // this is only called once per entity so numsurfaces is always 1, and
7392         // surfacelist is always {0}, so this code does not handle batches
7393
7394         if (rsurface.ent_flags & RENDER_ADDITIVE)
7395         {
7396                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7397                 GL_DepthMask(false);
7398         }
7399         else if (rsurface.colormod[3] < 1)
7400         {
7401                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7402                 GL_DepthMask(false);
7403         }
7404         else
7405         {
7406                 GL_BlendFunc(GL_ONE, GL_ZERO);
7407                 GL_DepthMask(true);
7408         }
7409         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7410         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7411         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7412         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7413         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7414         for (i = 0, c = color4f;i < 6;i++, c += 4)
7415         {
7416                 c[0] *= rsurface.colormod[0];
7417                 c[1] *= rsurface.colormod[1];
7418                 c[2] *= rsurface.colormod[2];
7419                 c[3] *= rsurface.colormod[3];
7420         }
7421         if (r_refdef.fogenabled)
7422         {
7423                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7424                 {
7425                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7426                         f2 = 1 - f1;
7427                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7428                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7429                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7430                 }
7431         }
7432 //      R_Mesh_ResetTextureState();
7433         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7434         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7435         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7436 }
7437
7438 void R_DrawNoModel(entity_render_t *ent)
7439 {
7440         vec3_t org;
7441         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7442         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7443                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7444         else
7445                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7446 }
7447
7448 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7449 {
7450         vec3_t right1, right2, diff, normal;
7451
7452         VectorSubtract (org2, org1, normal);
7453
7454         // calculate 'right' vector for start
7455         VectorSubtract (r_refdef.view.origin, org1, diff);
7456         CrossProduct (normal, diff, right1);
7457         VectorNormalize (right1);
7458
7459         // calculate 'right' vector for end
7460         VectorSubtract (r_refdef.view.origin, org2, diff);
7461         CrossProduct (normal, diff, right2);
7462         VectorNormalize (right2);
7463
7464         vert[ 0] = org1[0] + width * right1[0];
7465         vert[ 1] = org1[1] + width * right1[1];
7466         vert[ 2] = org1[2] + width * right1[2];
7467         vert[ 3] = org1[0] - width * right1[0];
7468         vert[ 4] = org1[1] - width * right1[1];
7469         vert[ 5] = org1[2] - width * right1[2];
7470         vert[ 6] = org2[0] - width * right2[0];
7471         vert[ 7] = org2[1] - width * right2[1];
7472         vert[ 8] = org2[2] - width * right2[2];
7473         vert[ 9] = org2[0] + width * right2[0];
7474         vert[10] = org2[1] + width * right2[1];
7475         vert[11] = org2[2] + width * right2[2];
7476 }
7477
7478 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)
7479 {
7480         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7481         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7482         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7483         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7484         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7485         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7486         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7487         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7488         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7489         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7490         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7491         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7492 }
7493
7494 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7495 {
7496         int i;
7497         float *vertex3f;
7498         float v[3];
7499         VectorSet(v, x, y, z);
7500         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7501                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7502                         break;
7503         if (i == mesh->numvertices)
7504         {
7505                 if (mesh->numvertices < mesh->maxvertices)
7506                 {
7507                         VectorCopy(v, vertex3f);
7508                         mesh->numvertices++;
7509                 }
7510                 return mesh->numvertices;
7511         }
7512         else
7513                 return i;
7514 }
7515
7516 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7517 {
7518         int i;
7519         int *e, element[3];
7520         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7521         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7522         e = mesh->element3i + mesh->numtriangles * 3;
7523         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7524         {
7525                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7526                 if (mesh->numtriangles < mesh->maxtriangles)
7527                 {
7528                         *e++ = element[0];
7529                         *e++ = element[1];
7530                         *e++ = element[2];
7531                         mesh->numtriangles++;
7532                 }
7533                 element[1] = element[2];
7534         }
7535 }
7536
7537 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7538 {
7539         int i;
7540         int *e, element[3];
7541         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7542         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7543         e = mesh->element3i + mesh->numtriangles * 3;
7544         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7545         {
7546                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7547                 if (mesh->numtriangles < mesh->maxtriangles)
7548                 {
7549                         *e++ = element[0];
7550                         *e++ = element[1];
7551                         *e++ = element[2];
7552                         mesh->numtriangles++;
7553                 }
7554                 element[1] = element[2];
7555         }
7556 }
7557
7558 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7559 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7560 {
7561         int planenum, planenum2;
7562         int w;
7563         int tempnumpoints;
7564         mplane_t *plane, *plane2;
7565         double maxdist;
7566         double temppoints[2][256*3];
7567         // figure out how large a bounding box we need to properly compute this brush
7568         maxdist = 0;
7569         for (w = 0;w < numplanes;w++)
7570                 maxdist = max(maxdist, fabs(planes[w].dist));
7571         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7572         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7573         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7574         {
7575                 w = 0;
7576                 tempnumpoints = 4;
7577                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7578                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7579                 {
7580                         if (planenum2 == planenum)
7581                                 continue;
7582                         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);
7583                         w = !w;
7584                 }
7585                 if (tempnumpoints < 3)
7586                         continue;
7587                 // generate elements forming a triangle fan for this polygon
7588                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7589         }
7590 }
7591
7592 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)
7593 {
7594         texturelayer_t *layer;
7595         layer = t->currentlayers + t->currentnumlayers++;
7596         layer->type = type;
7597         layer->depthmask = depthmask;
7598         layer->blendfunc1 = blendfunc1;
7599         layer->blendfunc2 = blendfunc2;
7600         layer->texture = texture;
7601         layer->texmatrix = *matrix;
7602         layer->color[0] = r;
7603         layer->color[1] = g;
7604         layer->color[2] = b;
7605         layer->color[3] = a;
7606 }
7607
7608 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7609 {
7610         if(parms[0] == 0 && parms[1] == 0)
7611                 return false;
7612         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7613                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7614                         return false;
7615         return true;
7616 }
7617
7618 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7619 {
7620         double index, f;
7621         index = parms[2] + rsurface.shadertime * parms[3];
7622         index -= floor(index);
7623         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7624         {
7625         default:
7626         case Q3WAVEFUNC_NONE:
7627         case Q3WAVEFUNC_NOISE:
7628         case Q3WAVEFUNC_COUNT:
7629                 f = 0;
7630                 break;
7631         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7632         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7633         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7634         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7635         case Q3WAVEFUNC_TRIANGLE:
7636                 index *= 4;
7637                 f = index - floor(index);
7638                 if (index < 1)
7639                 {
7640                         // f = f;
7641                 }
7642                 else if (index < 2)
7643                         f = 1 - f;
7644                 else if (index < 3)
7645                         f = -f;
7646                 else
7647                         f = -(1 - f);
7648                 break;
7649         }
7650         f = parms[0] + parms[1] * f;
7651         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7652                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7653         return (float) f;
7654 }
7655
7656 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7657 {
7658         int w, h, idx;
7659         double f;
7660         double offsetd[2];
7661         float tcmat[12];
7662         matrix4x4_t matrix, temp;
7663         switch(tcmod->tcmod)
7664         {
7665                 case Q3TCMOD_COUNT:
7666                 case Q3TCMOD_NONE:
7667                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7668                                 matrix = r_waterscrollmatrix;
7669                         else
7670                                 matrix = identitymatrix;
7671                         break;
7672                 case Q3TCMOD_ENTITYTRANSLATE:
7673                         // this is used in Q3 to allow the gamecode to control texcoord
7674                         // scrolling on the entity, which is not supported in darkplaces yet.
7675                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7676                         break;
7677                 case Q3TCMOD_ROTATE:
7678                         f = tcmod->parms[0] * rsurface.shadertime;
7679                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7680                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7681                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7682                         break;
7683                 case Q3TCMOD_SCALE:
7684                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7685                         break;
7686                 case Q3TCMOD_SCROLL:
7687                         // extra care is needed because of precision breakdown with large values of time
7688                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7689                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7690                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7691                         break;
7692                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7693                         w = (int) tcmod->parms[0];
7694                         h = (int) tcmod->parms[1];
7695                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7696                         f = f - floor(f);
7697                         idx = (int) floor(f * w * h);
7698                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7699                         break;
7700                 case Q3TCMOD_STRETCH:
7701                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7702                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7703                         break;
7704                 case Q3TCMOD_TRANSFORM:
7705                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7706                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7707                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7708                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7709                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7710                         break;
7711                 case Q3TCMOD_TURBULENT:
7712                         // this is handled in the RSurf_PrepareVertices function
7713                         matrix = identitymatrix;
7714                         break;
7715         }
7716         temp = *texmatrix;
7717         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7718 }
7719
7720 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7721 {
7722         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7723         char name[MAX_QPATH];
7724         skinframe_t *skinframe;
7725         unsigned char pixels[296*194];
7726         strlcpy(cache->name, skinname, sizeof(cache->name));
7727         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7728         if (developer_loading.integer)
7729                 Con_Printf("loading %s\n", name);
7730         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7731         if (!skinframe || !skinframe->base)
7732         {
7733                 unsigned char *f;
7734                 fs_offset_t filesize;
7735                 skinframe = NULL;
7736                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7737                 if (f)
7738                 {
7739                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7740                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7741                         Mem_Free(f);
7742                 }
7743         }
7744         cache->skinframe = skinframe;
7745 }
7746
7747 texture_t *R_GetCurrentTexture(texture_t *t)
7748 {
7749         int i;
7750         const entity_render_t *ent = rsurface.entity;
7751         dp_model_t *model = ent->model;
7752         q3shaderinfo_layer_tcmod_t *tcmod;
7753
7754         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7755                 return t->currentframe;
7756         t->update_lastrenderframe = r_textureframe;
7757         t->update_lastrenderentity = (void *)ent;
7758
7759         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7760                 t->camera_entity = ent->entitynumber;
7761         else
7762                 t->camera_entity = 0;
7763
7764         // switch to an alternate material if this is a q1bsp animated material
7765         {
7766                 texture_t *texture = t;
7767                 int s = rsurface.ent_skinnum;
7768                 if ((unsigned int)s >= (unsigned int)model->numskins)
7769                         s = 0;
7770                 if (model->skinscenes)
7771                 {
7772                         if (model->skinscenes[s].framecount > 1)
7773                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7774                         else
7775                                 s = model->skinscenes[s].firstframe;
7776                 }
7777                 if (s > 0)
7778                         t = t + s * model->num_surfaces;
7779                 if (t->animated)
7780                 {
7781                         // use an alternate animation if the entity's frame is not 0,
7782                         // and only if the texture has an alternate animation
7783                         if (rsurface.ent_alttextures && t->anim_total[1])
7784                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7785                         else
7786                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7787                 }
7788                 texture->currentframe = t;
7789         }
7790
7791         // update currentskinframe to be a qw skin or animation frame
7792         if (rsurface.ent_qwskin >= 0)
7793         {
7794                 i = rsurface.ent_qwskin;
7795                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7796                 {
7797                         r_qwskincache_size = cl.maxclients;
7798                         if (r_qwskincache)
7799                                 Mem_Free(r_qwskincache);
7800                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7801                 }
7802                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7803                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7804                 t->currentskinframe = r_qwskincache[i].skinframe;
7805                 if (t->currentskinframe == NULL)
7806                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7807         }
7808         else if (t->numskinframes >= 2)
7809                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7810         if (t->backgroundnumskinframes >= 2)
7811                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7812
7813         t->currentmaterialflags = t->basematerialflags;
7814         t->currentalpha = rsurface.colormod[3];
7815         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7816                 t->currentalpha *= r_wateralpha.value;
7817         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7818                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7819         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7820                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7821         if (!(rsurface.ent_flags & RENDER_LIGHT))
7822                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7823         else if (FAKELIGHT_ENABLED)
7824         {
7825                 // no modellight if using fakelight for the map
7826         }
7827         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7828         {
7829                 // pick a model lighting mode
7830                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7831                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7832                 else
7833                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7834         }
7835         if (rsurface.ent_flags & RENDER_ADDITIVE)
7836                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7837         else if (t->currentalpha < 1)
7838                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7839         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7840         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7841                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7842         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7843                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7844         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7845                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7846         if (t->backgroundnumskinframes)
7847                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7848         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7849         {
7850                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7851                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7852         }
7853         else
7854                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7855         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7856         {
7857                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7858                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7859         }
7860         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7861                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7862
7863         // there is no tcmod
7864         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7865         {
7866                 t->currenttexmatrix = r_waterscrollmatrix;
7867                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7868         }
7869         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7870         {
7871                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7872                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7873         }
7874
7875         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7876                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7877         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7878                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7879
7880         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7881         if (t->currentskinframe->qpixels)
7882                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7883         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7884         if (!t->basetexture)
7885                 t->basetexture = r_texture_notexture;
7886         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7887         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7888         t->nmaptexture = t->currentskinframe->nmap;
7889         if (!t->nmaptexture)
7890                 t->nmaptexture = r_texture_blanknormalmap;
7891         t->glosstexture = r_texture_black;
7892         t->glowtexture = t->currentskinframe->glow;
7893         t->fogtexture = t->currentskinframe->fog;
7894         t->reflectmasktexture = t->currentskinframe->reflect;
7895         if (t->backgroundnumskinframes)
7896         {
7897                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7898                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7899                 t->backgroundglosstexture = r_texture_black;
7900                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7901                 if (!t->backgroundnmaptexture)
7902                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7903         }
7904         else
7905         {
7906                 t->backgroundbasetexture = r_texture_white;
7907                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7908                 t->backgroundglosstexture = r_texture_black;
7909                 t->backgroundglowtexture = NULL;
7910         }
7911         t->specularpower = r_shadow_glossexponent.value;
7912         // TODO: store reference values for these in the texture?
7913         t->specularscale = 0;
7914         if (r_shadow_gloss.integer > 0)
7915         {
7916                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7917                 {
7918                         if (r_shadow_glossintensity.value > 0)
7919                         {
7920                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7921                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7922                                 t->specularscale = r_shadow_glossintensity.value;
7923                         }
7924                 }
7925                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7926                 {
7927                         t->glosstexture = r_texture_white;
7928                         t->backgroundglosstexture = r_texture_white;
7929                         t->specularscale = r_shadow_gloss2intensity.value;
7930                         t->specularpower = r_shadow_gloss2exponent.value;
7931                 }
7932         }
7933         t->specularscale *= t->specularscalemod;
7934         t->specularpower *= t->specularpowermod;
7935         t->rtlightambient = 0;
7936
7937         // lightmaps mode looks bad with dlights using actual texturing, so turn
7938         // off the colormap and glossmap, but leave the normalmap on as it still
7939         // accurately represents the shading involved
7940         if (gl_lightmaps.integer)
7941         {
7942                 t->basetexture = r_texture_grey128;
7943                 t->pantstexture = r_texture_black;
7944                 t->shirttexture = r_texture_black;
7945                 t->nmaptexture = r_texture_blanknormalmap;
7946                 t->glosstexture = r_texture_black;
7947                 t->glowtexture = NULL;
7948                 t->fogtexture = NULL;
7949                 t->reflectmasktexture = NULL;
7950                 t->backgroundbasetexture = NULL;
7951                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7952                 t->backgroundglosstexture = r_texture_black;
7953                 t->backgroundglowtexture = NULL;
7954                 t->specularscale = 0;
7955                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7956         }
7957
7958         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7959         VectorClear(t->dlightcolor);
7960         t->currentnumlayers = 0;
7961         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7962         {
7963                 int blendfunc1, blendfunc2;
7964                 qboolean depthmask;
7965                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7966                 {
7967                         blendfunc1 = GL_SRC_ALPHA;
7968                         blendfunc2 = GL_ONE;
7969                 }
7970                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7971                 {
7972                         blendfunc1 = GL_SRC_ALPHA;
7973                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7974                 }
7975                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7976                 {
7977                         blendfunc1 = t->customblendfunc[0];
7978                         blendfunc2 = t->customblendfunc[1];
7979                 }
7980                 else
7981                 {
7982                         blendfunc1 = GL_ONE;
7983                         blendfunc2 = GL_ZERO;
7984                 }
7985                 // don't colormod evilblend textures
7986                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7987                         VectorSet(t->lightmapcolor, 1, 1, 1);
7988                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7989                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7990                 {
7991                         // fullbright is not affected by r_refdef.lightmapintensity
7992                         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]);
7993                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7994                                 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]);
7995                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7996                                 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]);
7997                 }
7998                 else
7999                 {
8000                         vec3_t ambientcolor;
8001                         float colorscale;
8002                         // set the color tint used for lights affecting this surface
8003                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8004                         colorscale = 2;
8005                         // q3bsp has no lightmap updates, so the lightstylevalue that
8006                         // would normally be baked into the lightmap must be
8007                         // applied to the color
8008                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8009                         if (model->type == mod_brushq3)
8010                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8011                         colorscale *= r_refdef.lightmapintensity;
8012                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8013                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8014                         // basic lit geometry
8015                         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]);
8016                         // add pants/shirt if needed
8017                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8018                                 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]);
8019                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8020                                 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]);
8021                         // now add ambient passes if needed
8022                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8023                         {
8024                                 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]);
8025                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8026                                         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]);
8027                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8028                                         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]);
8029                         }
8030                 }
8031                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8032                         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]);
8033                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8034                 {
8035                         // if this is opaque use alpha blend which will darken the earlier
8036                         // passes cheaply.
8037                         //
8038                         // if this is an alpha blended material, all the earlier passes
8039                         // were darkened by fog already, so we only need to add the fog
8040                         // color ontop through the fog mask texture
8041                         //
8042                         // if this is an additive blended material, all the earlier passes
8043                         // were darkened by fog already, and we should not add fog color
8044                         // (because the background was not darkened, there is no fog color
8045                         // that was lost behind it).
8046                         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]);
8047                 }
8048         }
8049
8050         return t->currentframe;
8051 }
8052
8053 rsurfacestate_t rsurface;
8054
8055 void RSurf_ActiveWorldEntity(void)
8056 {
8057         dp_model_t *model = r_refdef.scene.worldmodel;
8058         //if (rsurface.entity == r_refdef.scene.worldentity)
8059         //      return;
8060         rsurface.entity = r_refdef.scene.worldentity;
8061         rsurface.skeleton = NULL;
8062         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8063         rsurface.ent_skinnum = 0;
8064         rsurface.ent_qwskin = -1;
8065         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8066         rsurface.shadertime = r_refdef.scene.time;
8067         rsurface.matrix = identitymatrix;
8068         rsurface.inversematrix = identitymatrix;
8069         rsurface.matrixscale = 1;
8070         rsurface.inversematrixscale = 1;
8071         R_EntityMatrix(&identitymatrix);
8072         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8073         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8074         rsurface.fograngerecip = r_refdef.fograngerecip;
8075         rsurface.fogheightfade = r_refdef.fogheightfade;
8076         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8077         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8078         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8079         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8080         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8081         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8082         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8083         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8084         rsurface.colormod[3] = 1;
8085         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);
8086         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8087         rsurface.frameblend[0].lerp = 1;
8088         rsurface.ent_alttextures = false;
8089         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8090         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8091         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8092         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8093         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8094         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8095         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8096         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8097         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8098         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8099         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8100         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8101         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8102         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8103         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8104         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8105         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8106         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8107         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8108         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8109         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8110         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8111         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8112         rsurface.modelelement3i = model->surfmesh.data_element3i;
8113         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8114         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8115         rsurface.modelelement3s = model->surfmesh.data_element3s;
8116         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8117         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8118         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8119         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8120         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8121         rsurface.modelsurfaces = model->data_surfaces;
8122         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8123         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8124         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8125         rsurface.modelgeneratedvertex = false;
8126         rsurface.batchgeneratedvertex = false;
8127         rsurface.batchfirstvertex = 0;
8128         rsurface.batchnumvertices = 0;
8129         rsurface.batchfirsttriangle = 0;
8130         rsurface.batchnumtriangles = 0;
8131         rsurface.batchvertex3f  = NULL;
8132         rsurface.batchvertex3f_vertexbuffer = NULL;
8133         rsurface.batchvertex3f_bufferoffset = 0;
8134         rsurface.batchsvector3f = NULL;
8135         rsurface.batchsvector3f_vertexbuffer = NULL;
8136         rsurface.batchsvector3f_bufferoffset = 0;
8137         rsurface.batchtvector3f = NULL;
8138         rsurface.batchtvector3f_vertexbuffer = NULL;
8139         rsurface.batchtvector3f_bufferoffset = 0;
8140         rsurface.batchnormal3f  = NULL;
8141         rsurface.batchnormal3f_vertexbuffer = NULL;
8142         rsurface.batchnormal3f_bufferoffset = 0;
8143         rsurface.batchlightmapcolor4f = NULL;
8144         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8145         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8146         rsurface.batchtexcoordtexture2f = NULL;
8147         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8148         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8149         rsurface.batchtexcoordlightmap2f = NULL;
8150         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8151         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8152         rsurface.batchvertexmesh = NULL;
8153         rsurface.batchvertexmeshbuffer = NULL;
8154         rsurface.batchvertex3fbuffer = NULL;
8155         rsurface.batchelement3i = NULL;
8156         rsurface.batchelement3i_indexbuffer = NULL;
8157         rsurface.batchelement3i_bufferoffset = 0;
8158         rsurface.batchelement3s = NULL;
8159         rsurface.batchelement3s_indexbuffer = NULL;
8160         rsurface.batchelement3s_bufferoffset = 0;
8161         rsurface.passcolor4f = NULL;
8162         rsurface.passcolor4f_vertexbuffer = NULL;
8163         rsurface.passcolor4f_bufferoffset = 0;
8164 }
8165
8166 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8167 {
8168         dp_model_t *model = ent->model;
8169         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8170         //      return;
8171         rsurface.entity = (entity_render_t *)ent;
8172         rsurface.skeleton = ent->skeleton;
8173         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8174         rsurface.ent_skinnum = ent->skinnum;
8175         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;
8176         rsurface.ent_flags = ent->flags;
8177         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8178         rsurface.matrix = ent->matrix;
8179         rsurface.inversematrix = ent->inversematrix;
8180         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8181         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8182         R_EntityMatrix(&rsurface.matrix);
8183         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8184         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8185         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8186         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8187         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8188         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8189         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8190         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8191         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8192         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8193         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8194         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8195         rsurface.colormod[3] = ent->alpha;
8196         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8197         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8198         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8199         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8200         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8201         if (ent->model->brush.submodel && !prepass)
8202         {
8203                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8204                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8205         }
8206         if (model->surfmesh.isanimated && model->AnimateVertices)
8207         {
8208                 if (ent->animcache_vertex3f)
8209                 {
8210                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8211                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8212                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8213                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8214                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8215                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8216                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8217                 }
8218                 else if (wanttangents)
8219                 {
8220                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8221                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8222                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8223                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8224                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8225                         rsurface.modelvertexmesh = NULL;
8226                         rsurface.modelvertexmeshbuffer = NULL;
8227                         rsurface.modelvertex3fbuffer = NULL;
8228                 }
8229                 else if (wantnormals)
8230                 {
8231                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8232                         rsurface.modelsvector3f = NULL;
8233                         rsurface.modeltvector3f = NULL;
8234                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8235                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8236                         rsurface.modelvertexmesh = NULL;
8237                         rsurface.modelvertexmeshbuffer = NULL;
8238                         rsurface.modelvertex3fbuffer = NULL;
8239                 }
8240                 else
8241                 {
8242                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8243                         rsurface.modelsvector3f = NULL;
8244                         rsurface.modeltvector3f = NULL;
8245                         rsurface.modelnormal3f = NULL;
8246                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8247                         rsurface.modelvertexmesh = NULL;
8248                         rsurface.modelvertexmeshbuffer = NULL;
8249                         rsurface.modelvertex3fbuffer = NULL;
8250                 }
8251                 rsurface.modelvertex3f_vertexbuffer = 0;
8252                 rsurface.modelvertex3f_bufferoffset = 0;
8253                 rsurface.modelsvector3f_vertexbuffer = 0;
8254                 rsurface.modelsvector3f_bufferoffset = 0;
8255                 rsurface.modeltvector3f_vertexbuffer = 0;
8256                 rsurface.modeltvector3f_bufferoffset = 0;
8257                 rsurface.modelnormal3f_vertexbuffer = 0;
8258                 rsurface.modelnormal3f_bufferoffset = 0;
8259                 rsurface.modelgeneratedvertex = true;
8260         }
8261         else
8262         {
8263                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8264                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8265                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8266                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8267                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8268                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8269                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8270                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8271                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8272                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8273                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8274                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8275                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8276                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8277                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8278                 rsurface.modelgeneratedvertex = false;
8279         }
8280         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8281         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8282         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8283         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8284         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8285         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8286         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8287         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8288         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8289         rsurface.modelelement3i = model->surfmesh.data_element3i;
8290         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8291         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8292         rsurface.modelelement3s = model->surfmesh.data_element3s;
8293         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8294         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8295         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8296         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8297         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8298         rsurface.modelsurfaces = model->data_surfaces;
8299         rsurface.batchgeneratedvertex = false;
8300         rsurface.batchfirstvertex = 0;
8301         rsurface.batchnumvertices = 0;
8302         rsurface.batchfirsttriangle = 0;
8303         rsurface.batchnumtriangles = 0;
8304         rsurface.batchvertex3f  = NULL;
8305         rsurface.batchvertex3f_vertexbuffer = NULL;
8306         rsurface.batchvertex3f_bufferoffset = 0;
8307         rsurface.batchsvector3f = NULL;
8308         rsurface.batchsvector3f_vertexbuffer = NULL;
8309         rsurface.batchsvector3f_bufferoffset = 0;
8310         rsurface.batchtvector3f = NULL;
8311         rsurface.batchtvector3f_vertexbuffer = NULL;
8312         rsurface.batchtvector3f_bufferoffset = 0;
8313         rsurface.batchnormal3f  = NULL;
8314         rsurface.batchnormal3f_vertexbuffer = NULL;
8315         rsurface.batchnormal3f_bufferoffset = 0;
8316         rsurface.batchlightmapcolor4f = NULL;
8317         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8318         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8319         rsurface.batchtexcoordtexture2f = NULL;
8320         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8321         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8322         rsurface.batchtexcoordlightmap2f = NULL;
8323         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8324         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8325         rsurface.batchvertexmesh = NULL;
8326         rsurface.batchvertexmeshbuffer = NULL;
8327         rsurface.batchvertex3fbuffer = NULL;
8328         rsurface.batchelement3i = NULL;
8329         rsurface.batchelement3i_indexbuffer = NULL;
8330         rsurface.batchelement3i_bufferoffset = 0;
8331         rsurface.batchelement3s = NULL;
8332         rsurface.batchelement3s_indexbuffer = NULL;
8333         rsurface.batchelement3s_bufferoffset = 0;
8334         rsurface.passcolor4f = NULL;
8335         rsurface.passcolor4f_vertexbuffer = NULL;
8336         rsurface.passcolor4f_bufferoffset = 0;
8337 }
8338
8339 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)
8340 {
8341         rsurface.entity = r_refdef.scene.worldentity;
8342         rsurface.skeleton = NULL;
8343         rsurface.ent_skinnum = 0;
8344         rsurface.ent_qwskin = -1;
8345         rsurface.ent_flags = entflags;
8346         rsurface.shadertime = r_refdef.scene.time - shadertime;
8347         rsurface.modelnumvertices = numvertices;
8348         rsurface.modelnumtriangles = numtriangles;
8349         rsurface.matrix = *matrix;
8350         rsurface.inversematrix = *inversematrix;
8351         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8352         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8353         R_EntityMatrix(&rsurface.matrix);
8354         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8355         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8356         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8357         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8358         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8359         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8360         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8361         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8362         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8363         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8364         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8365         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8366         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);
8367         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8368         rsurface.frameblend[0].lerp = 1;
8369         rsurface.ent_alttextures = false;
8370         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8371         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8372         if (wanttangents)
8373         {
8374                 rsurface.modelvertex3f = (float *)vertex3f;
8375                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8376                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8377                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8378         }
8379         else if (wantnormals)
8380         {
8381                 rsurface.modelvertex3f = (float *)vertex3f;
8382                 rsurface.modelsvector3f = NULL;
8383                 rsurface.modeltvector3f = NULL;
8384                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8385         }
8386         else
8387         {
8388                 rsurface.modelvertex3f = (float *)vertex3f;
8389                 rsurface.modelsvector3f = NULL;
8390                 rsurface.modeltvector3f = NULL;
8391                 rsurface.modelnormal3f = NULL;
8392         }
8393         rsurface.modelvertexmesh = NULL;
8394         rsurface.modelvertexmeshbuffer = NULL;
8395         rsurface.modelvertex3fbuffer = NULL;
8396         rsurface.modelvertex3f_vertexbuffer = 0;
8397         rsurface.modelvertex3f_bufferoffset = 0;
8398         rsurface.modelsvector3f_vertexbuffer = 0;
8399         rsurface.modelsvector3f_bufferoffset = 0;
8400         rsurface.modeltvector3f_vertexbuffer = 0;
8401         rsurface.modeltvector3f_bufferoffset = 0;
8402         rsurface.modelnormal3f_vertexbuffer = 0;
8403         rsurface.modelnormal3f_bufferoffset = 0;
8404         rsurface.modelgeneratedvertex = true;
8405         rsurface.modellightmapcolor4f  = (float *)color4f;
8406         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8407         rsurface.modellightmapcolor4f_bufferoffset = 0;
8408         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8409         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8410         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8411         rsurface.modeltexcoordlightmap2f  = NULL;
8412         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8413         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8414         rsurface.modelelement3i = (int *)element3i;
8415         rsurface.modelelement3i_indexbuffer = NULL;
8416         rsurface.modelelement3i_bufferoffset = 0;
8417         rsurface.modelelement3s = (unsigned short *)element3s;
8418         rsurface.modelelement3s_indexbuffer = NULL;
8419         rsurface.modelelement3s_bufferoffset = 0;
8420         rsurface.modellightmapoffsets = NULL;
8421         rsurface.modelsurfaces = NULL;
8422         rsurface.batchgeneratedvertex = false;
8423         rsurface.batchfirstvertex = 0;
8424         rsurface.batchnumvertices = 0;
8425         rsurface.batchfirsttriangle = 0;
8426         rsurface.batchnumtriangles = 0;
8427         rsurface.batchvertex3f  = NULL;
8428         rsurface.batchvertex3f_vertexbuffer = NULL;
8429         rsurface.batchvertex3f_bufferoffset = 0;
8430         rsurface.batchsvector3f = NULL;
8431         rsurface.batchsvector3f_vertexbuffer = NULL;
8432         rsurface.batchsvector3f_bufferoffset = 0;
8433         rsurface.batchtvector3f = NULL;
8434         rsurface.batchtvector3f_vertexbuffer = NULL;
8435         rsurface.batchtvector3f_bufferoffset = 0;
8436         rsurface.batchnormal3f  = NULL;
8437         rsurface.batchnormal3f_vertexbuffer = NULL;
8438         rsurface.batchnormal3f_bufferoffset = 0;
8439         rsurface.batchlightmapcolor4f = NULL;
8440         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8441         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8442         rsurface.batchtexcoordtexture2f = NULL;
8443         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8444         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8445         rsurface.batchtexcoordlightmap2f = NULL;
8446         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8447         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8448         rsurface.batchvertexmesh = NULL;
8449         rsurface.batchvertexmeshbuffer = NULL;
8450         rsurface.batchvertex3fbuffer = NULL;
8451         rsurface.batchelement3i = NULL;
8452         rsurface.batchelement3i_indexbuffer = NULL;
8453         rsurface.batchelement3i_bufferoffset = 0;
8454         rsurface.batchelement3s = NULL;
8455         rsurface.batchelement3s_indexbuffer = NULL;
8456         rsurface.batchelement3s_bufferoffset = 0;
8457         rsurface.passcolor4f = NULL;
8458         rsurface.passcolor4f_vertexbuffer = NULL;
8459         rsurface.passcolor4f_bufferoffset = 0;
8460
8461         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8462         {
8463                 if ((wantnormals || wanttangents) && !normal3f)
8464                 {
8465                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8466                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8467                 }
8468                 if (wanttangents && !svector3f)
8469                 {
8470                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8471                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8472                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8473                 }
8474         }
8475 }
8476
8477 float RSurf_FogPoint(const float *v)
8478 {
8479         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8480         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8481         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8482         float FogHeightFade = r_refdef.fogheightfade;
8483         float fogfrac;
8484         unsigned int fogmasktableindex;
8485         if (r_refdef.fogplaneviewabove)
8486                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8487         else
8488                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8489         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8490         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8491 }
8492
8493 float RSurf_FogVertex(const float *v)
8494 {
8495         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8496         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8497         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8498         float FogHeightFade = rsurface.fogheightfade;
8499         float fogfrac;
8500         unsigned int fogmasktableindex;
8501         if (r_refdef.fogplaneviewabove)
8502                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8503         else
8504                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8505         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8506         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8507 }
8508
8509 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8510 {
8511         int i;
8512         for (i = 0;i < numelements;i++)
8513                 outelement3i[i] = inelement3i[i] + adjust;
8514 }
8515
8516 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8517 extern cvar_t gl_vbo;
8518 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8519 {
8520         int deformindex;
8521         int firsttriangle;
8522         int numtriangles;
8523         int firstvertex;
8524         int endvertex;
8525         int numvertices;
8526         int surfacefirsttriangle;
8527         int surfacenumtriangles;
8528         int surfacefirstvertex;
8529         int surfaceendvertex;
8530         int surfacenumvertices;
8531         int batchnumvertices;
8532         int batchnumtriangles;
8533         int needsupdate;
8534         int i, j;
8535         qboolean gaps;
8536         qboolean dynamicvertex;
8537         float amplitude;
8538         float animpos;
8539         float scale;
8540         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8541         float waveparms[4];
8542         q3shaderinfo_deform_t *deform;
8543         const msurface_t *surface, *firstsurface;
8544         r_vertexmesh_t *vertexmesh;
8545         if (!texturenumsurfaces)
8546                 return;
8547         // find vertex range of this surface batch
8548         gaps = false;
8549         firstsurface = texturesurfacelist[0];
8550         firsttriangle = firstsurface->num_firsttriangle;
8551         batchnumvertices = 0;
8552         batchnumtriangles = 0;
8553         firstvertex = endvertex = firstsurface->num_firstvertex;
8554         for (i = 0;i < texturenumsurfaces;i++)
8555         {
8556                 surface = texturesurfacelist[i];
8557                 if (surface != firstsurface + i)
8558                         gaps = true;
8559                 surfacefirstvertex = surface->num_firstvertex;
8560                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8561                 surfacenumvertices = surface->num_vertices;
8562                 surfacenumtriangles = surface->num_triangles;
8563                 if (firstvertex > surfacefirstvertex)
8564                         firstvertex = surfacefirstvertex;
8565                 if (endvertex < surfaceendvertex)
8566                         endvertex = surfaceendvertex;
8567                 batchnumvertices += surfacenumvertices;
8568                 batchnumtriangles += surfacenumtriangles;
8569         }
8570
8571         // we now know the vertex range used, and if there are any gaps in it
8572         rsurface.batchfirstvertex = firstvertex;
8573         rsurface.batchnumvertices = endvertex - firstvertex;
8574         rsurface.batchfirsttriangle = firsttriangle;
8575         rsurface.batchnumtriangles = batchnumtriangles;
8576
8577         // this variable holds flags for which properties have been updated that
8578         // may require regenerating vertexmesh array...
8579         needsupdate = 0;
8580
8581         // check if any dynamic vertex processing must occur
8582         dynamicvertex = false;
8583
8584         // if there is a chance of animated vertex colors, it's a dynamic batch
8585         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8586         {
8587                 dynamicvertex = true;
8588                 batchneed |= BATCHNEED_NOGAPS;
8589                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8590         }
8591
8592         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8593         {
8594                 switch (deform->deform)
8595                 {
8596                 default:
8597                 case Q3DEFORM_PROJECTIONSHADOW:
8598                 case Q3DEFORM_TEXT0:
8599                 case Q3DEFORM_TEXT1:
8600                 case Q3DEFORM_TEXT2:
8601                 case Q3DEFORM_TEXT3:
8602                 case Q3DEFORM_TEXT4:
8603                 case Q3DEFORM_TEXT5:
8604                 case Q3DEFORM_TEXT6:
8605                 case Q3DEFORM_TEXT7:
8606                 case Q3DEFORM_NONE:
8607                         break;
8608                 case Q3DEFORM_AUTOSPRITE:
8609                         dynamicvertex = true;
8610                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8611                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8612                         break;
8613                 case Q3DEFORM_AUTOSPRITE2:
8614                         dynamicvertex = true;
8615                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8616                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8617                         break;
8618                 case Q3DEFORM_NORMAL:
8619                         dynamicvertex = true;
8620                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8621                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8622                         break;
8623                 case Q3DEFORM_WAVE:
8624                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8625                                 break; // if wavefunc is a nop, ignore this transform
8626                         dynamicvertex = true;
8627                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8628                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8629                         break;
8630                 case Q3DEFORM_BULGE:
8631                         dynamicvertex = true;
8632                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8633                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8634                         break;
8635                 case Q3DEFORM_MOVE:
8636                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8637                                 break; // if wavefunc is a nop, ignore this transform
8638                         dynamicvertex = true;
8639                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8640                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8641                         break;
8642                 }
8643         }
8644         switch(rsurface.texture->tcgen.tcgen)
8645         {
8646         default:
8647         case Q3TCGEN_TEXTURE:
8648                 break;
8649         case Q3TCGEN_LIGHTMAP:
8650                 dynamicvertex = true;
8651                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8652                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8653                 break;
8654         case Q3TCGEN_VECTOR:
8655                 dynamicvertex = true;
8656                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8657                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8658                 break;
8659         case Q3TCGEN_ENVIRONMENT:
8660                 dynamicvertex = true;
8661                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8662                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8663                 break;
8664         }
8665         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8666         {
8667                 dynamicvertex = true;
8668                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8669                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8670         }
8671
8672         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8673         {
8674                 dynamicvertex = true;
8675                 batchneed |= BATCHNEED_NOGAPS;
8676                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8677         }
8678
8679         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8680         {
8681                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8682                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8683                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8684                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8685                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8686                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8687                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8688         }
8689
8690         // when the model data has no vertex buffer (dynamic mesh), we need to
8691         // eliminate gaps
8692         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8693                 batchneed |= BATCHNEED_NOGAPS;
8694
8695         // if needsupdate, we have to do a dynamic vertex batch for sure
8696         if (needsupdate & batchneed)
8697                 dynamicvertex = true;
8698
8699         // see if we need to build vertexmesh from arrays
8700         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8701                 dynamicvertex = true;
8702
8703         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8704         // also some drivers strongly dislike firstvertex
8705         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8706                 dynamicvertex = true;
8707
8708         rsurface.batchvertex3f = rsurface.modelvertex3f;
8709         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8710         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8711         rsurface.batchsvector3f = rsurface.modelsvector3f;
8712         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8713         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8714         rsurface.batchtvector3f = rsurface.modeltvector3f;
8715         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8716         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8717         rsurface.batchnormal3f = rsurface.modelnormal3f;
8718         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8719         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8720         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8721         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8722         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8723         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8724         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8725         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8726         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8727         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8728         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8729         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8730         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8731         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8732         rsurface.batchelement3i = rsurface.modelelement3i;
8733         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8734         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8735         rsurface.batchelement3s = rsurface.modelelement3s;
8736         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8737         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8738
8739         // if any dynamic vertex processing has to occur in software, we copy the
8740         // entire surface list together before processing to rebase the vertices
8741         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8742         //
8743         // if any gaps exist and we do not have a static vertex buffer, we have to
8744         // copy the surface list together to avoid wasting upload bandwidth on the
8745         // vertices in the gaps.
8746         //
8747         // if gaps exist and we have a static vertex buffer, we still have to
8748         // combine the index buffer ranges into one dynamic index buffer.
8749         //
8750         // in all cases we end up with data that can be drawn in one call.
8751
8752         if (!dynamicvertex)
8753         {
8754                 // static vertex data, just set pointers...
8755                 rsurface.batchgeneratedvertex = false;
8756                 // if there are gaps, we want to build a combined index buffer,
8757                 // otherwise use the original static buffer with an appropriate offset
8758                 if (gaps)
8759                 {
8760                         // build a new triangle elements array for this batch
8761                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8762                         rsurface.batchfirsttriangle = 0;
8763                         numtriangles = 0;
8764                         for (i = 0;i < texturenumsurfaces;i++)
8765                         {
8766                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8767                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8768                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8769                                 numtriangles += surfacenumtriangles;
8770                         }
8771                         rsurface.batchelement3i_indexbuffer = NULL;
8772                         rsurface.batchelement3i_bufferoffset = 0;
8773                         rsurface.batchelement3s = NULL;
8774                         rsurface.batchelement3s_indexbuffer = NULL;
8775                         rsurface.batchelement3s_bufferoffset = 0;
8776                         if (endvertex <= 65536)
8777                         {
8778                                 // make a 16bit (unsigned short) index array if possible
8779                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8780                                 for (i = 0;i < numtriangles*3;i++)
8781                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8782                         }
8783                 }
8784                 return;
8785         }
8786
8787         // something needs software processing, do it for real...
8788         // we only directly handle separate array data in this case and then
8789         // generate interleaved data if needed...
8790         rsurface.batchgeneratedvertex = true;
8791
8792         // now copy the vertex data into a combined array and make an index array
8793         // (this is what Quake3 does all the time)
8794         //if (gaps || rsurface.batchfirstvertex)
8795         {
8796                 rsurface.batchvertex3fbuffer = NULL;
8797                 rsurface.batchvertexmesh = NULL;
8798                 rsurface.batchvertexmeshbuffer = NULL;
8799                 rsurface.batchvertex3f = NULL;
8800                 rsurface.batchvertex3f_vertexbuffer = NULL;
8801                 rsurface.batchvertex3f_bufferoffset = 0;
8802                 rsurface.batchsvector3f = NULL;
8803                 rsurface.batchsvector3f_vertexbuffer = NULL;
8804                 rsurface.batchsvector3f_bufferoffset = 0;
8805                 rsurface.batchtvector3f = NULL;
8806                 rsurface.batchtvector3f_vertexbuffer = NULL;
8807                 rsurface.batchtvector3f_bufferoffset = 0;
8808                 rsurface.batchnormal3f = NULL;
8809                 rsurface.batchnormal3f_vertexbuffer = NULL;
8810                 rsurface.batchnormal3f_bufferoffset = 0;
8811                 rsurface.batchlightmapcolor4f = NULL;
8812                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8813                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8814                 rsurface.batchtexcoordtexture2f = NULL;
8815                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8816                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8817                 rsurface.batchtexcoordlightmap2f = NULL;
8818                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8819                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8820                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8821                 rsurface.batchelement3i_indexbuffer = NULL;
8822                 rsurface.batchelement3i_bufferoffset = 0;
8823                 rsurface.batchelement3s = NULL;
8824                 rsurface.batchelement3s_indexbuffer = NULL;
8825                 rsurface.batchelement3s_bufferoffset = 0;
8826                 // we'll only be setting up certain arrays as needed
8827                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8828                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8829                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8830                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8831                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8832                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8833                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8834                 {
8835                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8836                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8837                 }
8838                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8839                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8840                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8841                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8842                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8843                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8844                 numvertices = 0;
8845                 numtriangles = 0;
8846                 for (i = 0;i < texturenumsurfaces;i++)
8847                 {
8848                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8849                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8850                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8851                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8852                         // copy only the data requested
8853                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8854                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8855                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8856                         {
8857                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8858                                 {
8859                                         if (rsurface.batchvertex3f)
8860                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8861                                         else
8862                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8863                                 }
8864                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8865                                 {
8866                                         if (rsurface.modelnormal3f)
8867                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8868                                         else
8869                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8870                                 }
8871                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8872                                 {
8873                                         if (rsurface.modelsvector3f)
8874                                         {
8875                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8876                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8877                                         }
8878                                         else
8879                                         {
8880                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8881                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8882                                         }
8883                                 }
8884                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8885                                 {
8886                                         if (rsurface.modellightmapcolor4f)
8887                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8888                                         else
8889                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8890                                 }
8891                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8892                                 {
8893                                         if (rsurface.modeltexcoordtexture2f)
8894                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8895                                         else
8896                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8897                                 }
8898                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8899                                 {
8900                                         if (rsurface.modeltexcoordlightmap2f)
8901                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8902                                         else
8903                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8904                                 }
8905                         }
8906                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8907                         numvertices += surfacenumvertices;
8908                         numtriangles += surfacenumtriangles;
8909                 }
8910
8911                 // generate a 16bit index array as well if possible
8912                 // (in general, dynamic batches fit)
8913                 if (numvertices <= 65536)
8914                 {
8915                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8916                         for (i = 0;i < numtriangles*3;i++)
8917                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8918                 }
8919
8920                 // since we've copied everything, the batch now starts at 0
8921                 rsurface.batchfirstvertex = 0;
8922                 rsurface.batchnumvertices = batchnumvertices;
8923                 rsurface.batchfirsttriangle = 0;
8924                 rsurface.batchnumtriangles = batchnumtriangles;
8925         }
8926
8927         // q1bsp surfaces rendered in vertex color mode have to have colors
8928         // calculated based on lightstyles
8929         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8930         {
8931                 // generate color arrays for the surfaces in this list
8932                 int c[4];
8933                 int scale;
8934                 int size3;
8935                 const int *offsets;
8936                 const unsigned char *lm;
8937                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8938                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8939                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8940                 numvertices = 0;
8941                 for (i = 0;i < texturenumsurfaces;i++)
8942                 {
8943                         surface = texturesurfacelist[i];
8944                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8945                         surfacenumvertices = surface->num_vertices;
8946                         if (surface->lightmapinfo->samples)
8947                         {
8948                                 for (j = 0;j < surfacenumvertices;j++)
8949                                 {
8950                                         lm = surface->lightmapinfo->samples + offsets[j];
8951                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8952                                         VectorScale(lm, scale, c);
8953                                         if (surface->lightmapinfo->styles[1] != 255)
8954                                         {
8955                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8956                                                 lm += size3;
8957                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8958                                                 VectorMA(c, scale, lm, c);
8959                                                 if (surface->lightmapinfo->styles[2] != 255)
8960                                                 {
8961                                                         lm += size3;
8962                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8963                                                         VectorMA(c, scale, lm, c);
8964                                                         if (surface->lightmapinfo->styles[3] != 255)
8965                                                         {
8966                                                                 lm += size3;
8967                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8968                                                                 VectorMA(c, scale, lm, c);
8969                                                         }
8970                                                 }
8971                                         }
8972                                         c[0] >>= 7;
8973                                         c[1] >>= 7;
8974                                         c[2] >>= 7;
8975                                         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);
8976                                         numvertices++;
8977                                 }
8978                         }
8979                         else
8980                         {
8981                                 for (j = 0;j < surfacenumvertices;j++)
8982                                 {
8983                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8984                                         numvertices++;
8985                                 }
8986                         }
8987                 }
8988         }
8989
8990         // if vertices are deformed (sprite flares and things in maps, possibly
8991         // water waves, bulges and other deformations), modify the copied vertices
8992         // in place
8993         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8994         {
8995                 switch (deform->deform)
8996                 {
8997                 default:
8998                 case Q3DEFORM_PROJECTIONSHADOW:
8999                 case Q3DEFORM_TEXT0:
9000                 case Q3DEFORM_TEXT1:
9001                 case Q3DEFORM_TEXT2:
9002                 case Q3DEFORM_TEXT3:
9003                 case Q3DEFORM_TEXT4:
9004                 case Q3DEFORM_TEXT5:
9005                 case Q3DEFORM_TEXT6:
9006                 case Q3DEFORM_TEXT7:
9007                 case Q3DEFORM_NONE:
9008                         break;
9009                 case Q3DEFORM_AUTOSPRITE:
9010                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9011                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9012                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9013                         VectorNormalize(newforward);
9014                         VectorNormalize(newright);
9015                         VectorNormalize(newup);
9016 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9017 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9018 //                      rsurface.batchvertex3f_bufferoffset = 0;
9019 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9020 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9021 //                      rsurface.batchsvector3f_bufferoffset = 0;
9022 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9023 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9024 //                      rsurface.batchtvector3f_bufferoffset = 0;
9025 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9026 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9027 //                      rsurface.batchnormal3f_bufferoffset = 0;
9028                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9029                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9030                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9031                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9032                                 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);
9033                         // a single autosprite surface can contain multiple sprites...
9034                         for (j = 0;j < batchnumvertices - 3;j += 4)
9035                         {
9036                                 VectorClear(center);
9037                                 for (i = 0;i < 4;i++)
9038                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9039                                 VectorScale(center, 0.25f, center);
9040                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9041                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9042                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9043                                 for (i = 0;i < 4;i++)
9044                                 {
9045                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9046                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9047                                 }
9048                         }
9049                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9050                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9051                         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);
9052                         break;
9053                 case Q3DEFORM_AUTOSPRITE2:
9054                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9055                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9056                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9057                         VectorNormalize(newforward);
9058                         VectorNormalize(newright);
9059                         VectorNormalize(newup);
9060 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9061 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9062 //                      rsurface.batchvertex3f_bufferoffset = 0;
9063                         {
9064                                 const float *v1, *v2;
9065                                 vec3_t start, end;
9066                                 float f, l;
9067                                 struct
9068                                 {
9069                                         float length2;
9070                                         const float *v1;
9071                                         const float *v2;
9072                                 }
9073                                 shortest[2];
9074                                 memset(shortest, 0, sizeof(shortest));
9075                                 // a single autosprite surface can contain multiple sprites...
9076                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9077                                 {
9078                                         VectorClear(center);
9079                                         for (i = 0;i < 4;i++)
9080                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9081                                         VectorScale(center, 0.25f, center);
9082                                         // find the two shortest edges, then use them to define the
9083                                         // axis vectors for rotating around the central axis
9084                                         for (i = 0;i < 6;i++)
9085                                         {
9086                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9087                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9088                                                 l = VectorDistance2(v1, v2);
9089                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9090                                                 if (v1[2] != v2[2])
9091                                                         l += (1.0f / 1024.0f);
9092                                                 if (shortest[0].length2 > l || i == 0)
9093                                                 {
9094                                                         shortest[1] = shortest[0];
9095                                                         shortest[0].length2 = l;
9096                                                         shortest[0].v1 = v1;
9097                                                         shortest[0].v2 = v2;
9098                                                 }
9099                                                 else if (shortest[1].length2 > l || i == 1)
9100                                                 {
9101                                                         shortest[1].length2 = l;
9102                                                         shortest[1].v1 = v1;
9103                                                         shortest[1].v2 = v2;
9104                                                 }
9105                                         }
9106                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9107                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9108                                         // this calculates the right vector from the shortest edge
9109                                         // and the up vector from the edge midpoints
9110                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9111                                         VectorNormalize(right);
9112                                         VectorSubtract(end, start, up);
9113                                         VectorNormalize(up);
9114                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9115                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9116                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9117                                         VectorNegate(forward, forward);
9118                                         VectorReflect(forward, 0, up, forward);
9119                                         VectorNormalize(forward);
9120                                         CrossProduct(up, forward, newright);
9121                                         VectorNormalize(newright);
9122                                         // rotate the quad around the up axis vector, this is made
9123                                         // especially easy by the fact we know the quad is flat,
9124                                         // so we only have to subtract the center position and
9125                                         // measure distance along the right vector, and then
9126                                         // multiply that by the newright vector and add back the
9127                                         // center position
9128                                         // we also need to subtract the old position to undo the
9129                                         // displacement from the center, which we do with a
9130                                         // DotProduct, the subtraction/addition of center is also
9131                                         // optimized into DotProducts here
9132                                         l = DotProduct(right, center);
9133                                         for (i = 0;i < 4;i++)
9134                                         {
9135                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9136                                                 f = DotProduct(right, v1) - l;
9137                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9138                                         }
9139                                 }
9140                         }
9141                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9142                         {
9143 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9144 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9145 //                              rsurface.batchnormal3f_bufferoffset = 0;
9146                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9147                         }
9148                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9149                         {
9150 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9151 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9152 //                              rsurface.batchsvector3f_bufferoffset = 0;
9153 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9154 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9155 //                              rsurface.batchtvector3f_bufferoffset = 0;
9156                                 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);
9157                         }
9158                         break;
9159                 case Q3DEFORM_NORMAL:
9160                         // deform the normals to make reflections wavey
9161                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9162                         rsurface.batchnormal3f_vertexbuffer = NULL;
9163                         rsurface.batchnormal3f_bufferoffset = 0;
9164                         for (j = 0;j < batchnumvertices;j++)
9165                         {
9166                                 float vertex[3];
9167                                 float *normal = rsurface.batchnormal3f + 3*j;
9168                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9169                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9170                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9171                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9172                                 VectorNormalize(normal);
9173                         }
9174                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9175                         {
9176 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9178 //                              rsurface.batchsvector3f_bufferoffset = 0;
9179 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9180 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9181 //                              rsurface.batchtvector3f_bufferoffset = 0;
9182                                 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);
9183                         }
9184                         break;
9185                 case Q3DEFORM_WAVE:
9186                         // deform vertex array to make wavey water and flags and such
9187                         waveparms[0] = deform->waveparms[0];
9188                         waveparms[1] = deform->waveparms[1];
9189                         waveparms[2] = deform->waveparms[2];
9190                         waveparms[3] = deform->waveparms[3];
9191                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9192                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9193                         // this is how a divisor of vertex influence on deformation
9194                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9195                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9196 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9197 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9198 //                      rsurface.batchvertex3f_bufferoffset = 0;
9199 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9200 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9201 //                      rsurface.batchnormal3f_bufferoffset = 0;
9202                         for (j = 0;j < batchnumvertices;j++)
9203                         {
9204                                 // if the wavefunc depends on time, evaluate it per-vertex
9205                                 if (waveparms[3])
9206                                 {
9207                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9208                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9209                                 }
9210                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9211                         }
9212                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9213                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9214                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9215                         {
9216 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9218 //                              rsurface.batchsvector3f_bufferoffset = 0;
9219 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9220 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9221 //                              rsurface.batchtvector3f_bufferoffset = 0;
9222                                 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);
9223                         }
9224                         break;
9225                 case Q3DEFORM_BULGE:
9226                         // deform vertex array to make the surface have moving bulges
9227 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9228 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9229 //                      rsurface.batchvertex3f_bufferoffset = 0;
9230 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9231 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9232 //                      rsurface.batchnormal3f_bufferoffset = 0;
9233                         for (j = 0;j < batchnumvertices;j++)
9234                         {
9235                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9236                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9237                         }
9238                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9239                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9240                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9241                         {
9242 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9243 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9244 //                              rsurface.batchsvector3f_bufferoffset = 0;
9245 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9246 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9247 //                              rsurface.batchtvector3f_bufferoffset = 0;
9248                                 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);
9249                         }
9250                         break;
9251                 case Q3DEFORM_MOVE:
9252                         // deform vertex array
9253                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9254                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9255                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9256                         VectorScale(deform->parms, scale, waveparms);
9257 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9258 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9259 //                      rsurface.batchvertex3f_bufferoffset = 0;
9260                         for (j = 0;j < batchnumvertices;j++)
9261                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9262                         break;
9263                 }
9264         }
9265
9266         // generate texcoords based on the chosen texcoord source
9267         switch(rsurface.texture->tcgen.tcgen)
9268         {
9269         default:
9270         case Q3TCGEN_TEXTURE:
9271                 break;
9272         case Q3TCGEN_LIGHTMAP:
9273 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9274 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9275 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9276                 if (rsurface.batchtexcoordlightmap2f)
9277                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9278                 break;
9279         case Q3TCGEN_VECTOR:
9280 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9281 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9282 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9283                 for (j = 0;j < batchnumvertices;j++)
9284                 {
9285                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9286                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9287                 }
9288                 break;
9289         case Q3TCGEN_ENVIRONMENT:
9290                 // make environment reflections using a spheremap
9291                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9292                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9293                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9294                 for (j = 0;j < batchnumvertices;j++)
9295                 {
9296                         // identical to Q3A's method, but executed in worldspace so
9297                         // carried models can be shiny too
9298
9299                         float viewer[3], d, reflected[3], worldreflected[3];
9300
9301                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9302                         // VectorNormalize(viewer);
9303
9304                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9305
9306                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9307                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9308                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9309                         // note: this is proportinal to viewer, so we can normalize later
9310
9311                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9312                         VectorNormalize(worldreflected);
9313
9314                         // note: this sphere map only uses world x and z!
9315                         // so positive and negative y will LOOK THE SAME.
9316                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9317                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9318                 }
9319                 break;
9320         }
9321         // the only tcmod that needs software vertex processing is turbulent, so
9322         // check for it here and apply the changes if needed
9323         // and we only support that as the first one
9324         // (handling a mixture of turbulent and other tcmods would be problematic
9325         //  without punting it entirely to a software path)
9326         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9327         {
9328                 amplitude = rsurface.texture->tcmods[0].parms[1];
9329                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9330 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9331 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9332 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9333                 for (j = 0;j < batchnumvertices;j++)
9334                 {
9335                         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);
9336                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9337                 }
9338         }
9339
9340         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9341         {
9342                 // convert the modified arrays to vertex structs
9343 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9344 //              rsurface.batchvertexmeshbuffer = NULL;
9345                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9346                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9347                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9348                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9349                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9350                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9351                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9352                 {
9353                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9354                         {
9355                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9356                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9357                         }
9358                 }
9359                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9360                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9361                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9362                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9363                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9364                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9365                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9366                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9367                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9368         }
9369 }
9370
9371 void RSurf_DrawBatch(void)
9372 {
9373         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9374         // through the pipeline, killing it earlier in the pipeline would have
9375         // per-surface overhead rather than per-batch overhead, so it's best to
9376         // reject it here, before it hits glDraw.
9377         if (rsurface.batchnumtriangles == 0)
9378                 return;
9379 #if 0
9380         // batch debugging code
9381         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9382         {
9383                 int i;
9384                 int j;
9385                 int c;
9386                 const int *e;
9387                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9388                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9389                 {
9390                         c = e[i];
9391                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9392                         {
9393                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9394                                 {
9395                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9396                                                 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);
9397                                         break;
9398                                 }
9399                         }
9400                 }
9401         }
9402 #endif
9403         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);
9404 }
9405
9406 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9407 {
9408         // pick the closest matching water plane
9409         int planeindex, vertexindex, bestplaneindex = -1;
9410         float d, bestd;
9411         vec3_t vert;
9412         const float *v;
9413         r_waterstate_waterplane_t *p;
9414         qboolean prepared = false;
9415         bestd = 0;
9416         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9417         {
9418                 if(p->camera_entity != rsurface.texture->camera_entity)
9419                         continue;
9420                 d = 0;
9421                 if(!prepared)
9422                 {
9423                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9424                         prepared = true;
9425                         if(rsurface.batchnumvertices == 0)
9426                                 break;
9427                 }
9428                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9429                 {
9430                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9431                         d += fabs(PlaneDiff(vert, &p->plane));
9432                 }
9433                 if (bestd > d || bestplaneindex < 0)
9434                 {
9435                         bestd = d;
9436                         bestplaneindex = planeindex;
9437                 }
9438         }
9439         return bestplaneindex;
9440         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9441         // this situation though, as it might be better to render single larger
9442         // batches with useless stuff (backface culled for example) than to
9443         // render multiple smaller batches
9444 }
9445
9446 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9447 {
9448         int i;
9449         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9450         rsurface.passcolor4f_vertexbuffer = 0;
9451         rsurface.passcolor4f_bufferoffset = 0;
9452         for (i = 0;i < rsurface.batchnumvertices;i++)
9453                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9454 }
9455
9456 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9457 {
9458         int i;
9459         float f;
9460         const float *v;
9461         const float *c;
9462         float *c2;
9463         if (rsurface.passcolor4f)
9464         {
9465                 // generate color arrays
9466                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9467                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9468                 rsurface.passcolor4f_vertexbuffer = 0;
9469                 rsurface.passcolor4f_bufferoffset = 0;
9470                 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)
9471                 {
9472                         f = RSurf_FogVertex(v);
9473                         c2[0] = c[0] * f;
9474                         c2[1] = c[1] * f;
9475                         c2[2] = c[2] * f;
9476                         c2[3] = c[3];
9477                 }
9478         }
9479         else
9480         {
9481                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9482                 rsurface.passcolor4f_vertexbuffer = 0;
9483                 rsurface.passcolor4f_bufferoffset = 0;
9484                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9485                 {
9486                         f = RSurf_FogVertex(v);
9487                         c2[0] = f;
9488                         c2[1] = f;
9489                         c2[2] = f;
9490                         c2[3] = 1;
9491                 }
9492         }
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9496 {
9497         int i;
9498         float f;
9499         const float *v;
9500         const float *c;
9501         float *c2;
9502         if (!rsurface.passcolor4f)
9503                 return;
9504         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9505         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9506         rsurface.passcolor4f_vertexbuffer = 0;
9507         rsurface.passcolor4f_bufferoffset = 0;
9508         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)
9509         {
9510                 f = RSurf_FogVertex(v);
9511                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9512                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9513                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9514                 c2[3] = c[3];
9515         }
9516 }
9517
9518 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9519 {
9520         int i;
9521         const float *c;
9522         float *c2;
9523         if (!rsurface.passcolor4f)
9524                 return;
9525         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
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, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9530         {
9531                 c2[0] = c[0] * r;
9532                 c2[1] = c[1] * g;
9533                 c2[2] = c[2] * b;
9534                 c2[3] = c[3] * a;
9535         }
9536 }
9537
9538 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9539 {
9540         int i;
9541         const float *c;
9542         float *c2;
9543         if (!rsurface.passcolor4f)
9544                 return;
9545         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9546         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9547         rsurface.passcolor4f_vertexbuffer = 0;
9548         rsurface.passcolor4f_bufferoffset = 0;
9549         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9550         {
9551                 c2[0] = c[0] + r_refdef.scene.ambient;
9552                 c2[1] = c[1] + r_refdef.scene.ambient;
9553                 c2[2] = c[2] + r_refdef.scene.ambient;
9554                 c2[3] = c[3];
9555         }
9556 }
9557
9558 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9559 {
9560         // TODO: optimize
9561         rsurface.passcolor4f = NULL;
9562         rsurface.passcolor4f_vertexbuffer = 0;
9563         rsurface.passcolor4f_bufferoffset = 0;
9564         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9565         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9566         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9567         GL_Color(r, g, b, a);
9568         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9569         RSurf_DrawBatch();
9570 }
9571
9572 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9573 {
9574         // TODO: optimize applyfog && applycolor case
9575         // just apply fog if necessary, and tint the fog color array if necessary
9576         rsurface.passcolor4f = NULL;
9577         rsurface.passcolor4f_vertexbuffer = 0;
9578         rsurface.passcolor4f_bufferoffset = 0;
9579         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9580         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9581         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9582         GL_Color(r, g, b, a);
9583         RSurf_DrawBatch();
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9587 {
9588         // TODO: optimize
9589         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9590         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9591         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9592         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9593         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9594         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9595         GL_Color(r, g, b, a);
9596         RSurf_DrawBatch();
9597 }
9598
9599 static void RSurf_DrawBatch_GL11_ClampColor(void)
9600 {
9601         int i;
9602         const float *c1;
9603         float *c2;
9604         if (!rsurface.passcolor4f)
9605                 return;
9606         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9607         {
9608                 c2[0] = bound(0.0f, c1[0], 1.0f);
9609                 c2[1] = bound(0.0f, c1[1], 1.0f);
9610                 c2[2] = bound(0.0f, c1[2], 1.0f);
9611                 c2[3] = bound(0.0f, c1[3], 1.0f);
9612         }
9613 }
9614
9615 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9616 {
9617         int i;
9618         float f;
9619         const float *v;
9620         const float *n;
9621         float *c;
9622         //vec3_t eyedir;
9623
9624         // fake shading
9625         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9626         rsurface.passcolor4f_vertexbuffer = 0;
9627         rsurface.passcolor4f_bufferoffset = 0;
9628         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)
9629         {
9630                 f = -DotProduct(r_refdef.view.forward, n);
9631                 f = max(0, f);
9632                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9633                 f *= r_refdef.lightmapintensity;
9634                 Vector4Set(c, f, f, f, 1);
9635         }
9636 }
9637
9638 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9639 {
9640         RSurf_DrawBatch_GL11_ApplyFakeLight();
9641         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9642         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9643         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9644         GL_Color(r, g, b, a);
9645         RSurf_DrawBatch();
9646 }
9647
9648 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9649 {
9650         int i;
9651         float f;
9652         float alpha;
9653         const float *v;
9654         const float *n;
9655         float *c;
9656         vec3_t ambientcolor;
9657         vec3_t diffusecolor;
9658         vec3_t lightdir;
9659         // TODO: optimize
9660         // model lighting
9661         VectorCopy(rsurface.modellight_lightdir, lightdir);
9662         f = 0.5f * r_refdef.lightmapintensity;
9663         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9664         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9665         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9666         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9667         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9668         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9669         alpha = *a;
9670         if (VectorLength2(diffusecolor) > 0)
9671         {
9672                 // q3-style directional shading
9673                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9674                 rsurface.passcolor4f_vertexbuffer = 0;
9675                 rsurface.passcolor4f_bufferoffset = 0;
9676                 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)
9677                 {
9678                         if ((f = DotProduct(n, lightdir)) > 0)
9679                                 VectorMA(ambientcolor, f, diffusecolor, c);
9680                         else
9681                                 VectorCopy(ambientcolor, c);
9682                         c[3] = alpha;
9683                 }
9684                 *r = 1;
9685                 *g = 1;
9686                 *b = 1;
9687                 *a = 1;
9688                 *applycolor = false;
9689         }
9690         else
9691         {
9692                 *r = ambientcolor[0];
9693                 *g = ambientcolor[1];
9694                 *b = ambientcolor[2];
9695                 rsurface.passcolor4f = NULL;
9696                 rsurface.passcolor4f_vertexbuffer = 0;
9697                 rsurface.passcolor4f_bufferoffset = 0;
9698         }
9699 }
9700
9701 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9702 {
9703         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9704         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9705         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9706         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9707         GL_Color(r, g, b, a);
9708         RSurf_DrawBatch();
9709 }
9710
9711 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9712 {
9713         int i;
9714         float f;
9715         const float *v;
9716         float *c;
9717
9718         // fake shading
9719         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9720         rsurface.passcolor4f_vertexbuffer = 0;
9721         rsurface.passcolor4f_bufferoffset = 0;
9722
9723         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9724         {
9725                 f = 1 - RSurf_FogVertex(v);
9726                 c[0] = r;
9727                 c[1] = g;
9728                 c[2] = b;
9729                 c[3] = f * a;
9730         }
9731 }
9732
9733 void RSurf_SetupDepthAndCulling(void)
9734 {
9735         // submodels are biased to avoid z-fighting with world surfaces that they
9736         // may be exactly overlapping (avoids z-fighting artifacts on certain
9737         // doors and things in Quake maps)
9738         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9739         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9740         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9741         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9742 }
9743
9744 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9745 {
9746         // transparent sky would be ridiculous
9747         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9748                 return;
9749         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9750         skyrenderlater = true;
9751         RSurf_SetupDepthAndCulling();
9752         GL_DepthMask(true);
9753         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9754         // skymasking on them, and Quake3 never did sky masking (unlike
9755         // software Quake and software Quake2), so disable the sky masking
9756         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9757         // and skymasking also looks very bad when noclipping outside the
9758         // level, so don't use it then either.
9759         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9760         {
9761                 R_Mesh_ResetTextureState();
9762                 if (skyrendermasked)
9763                 {
9764                         R_SetupShader_DepthOrShadow(false);
9765                         // depth-only (masking)
9766                         GL_ColorMask(0,0,0,0);
9767                         // just to make sure that braindead drivers don't draw
9768                         // anything despite that colormask...
9769                         GL_BlendFunc(GL_ZERO, GL_ONE);
9770                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9771                         if (rsurface.batchvertex3fbuffer)
9772                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9773                         else
9774                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9775                 }
9776                 else
9777                 {
9778                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9779                         // fog sky
9780                         GL_BlendFunc(GL_ONE, GL_ZERO);
9781                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9782                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9783                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9784                 }
9785                 RSurf_DrawBatch();
9786                 if (skyrendermasked)
9787                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9788         }
9789         R_Mesh_ResetTextureState();
9790         GL_Color(1, 1, 1, 1);
9791 }
9792
9793 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9794 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9795 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9796 {
9797         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9798                 return;
9799         if (prepass)
9800         {
9801                 // render screenspace normalmap to texture
9802                 GL_DepthMask(true);
9803                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9804                 RSurf_DrawBatch();
9805         }
9806
9807         // bind lightmap texture
9808
9809         // water/refraction/reflection/camera surfaces have to be handled specially
9810         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9811         {
9812                 int start, end, startplaneindex;
9813                 for (start = 0;start < texturenumsurfaces;start = end)
9814                 {
9815                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9816                         if(startplaneindex < 0)
9817                         {
9818                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9819                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9820                                 end = start + 1;
9821                                 continue;
9822                         }
9823                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9824                                 ;
9825                         // now that we have a batch using the same planeindex, render it
9826                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9827                         {
9828                                 // render water or distortion background
9829                                 GL_DepthMask(true);
9830                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BACKGROUND, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9831                                 RSurf_DrawBatch();
9832                                 // blend surface on top
9833                                 GL_DepthMask(false);
9834                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9835                                 RSurf_DrawBatch();
9836                         }
9837                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9838                         {
9839                                 // render surface with reflection texture as input
9840                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9841                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
9842                                 RSurf_DrawBatch();
9843                         }
9844                 }
9845                 return;
9846         }
9847
9848         // render surface batch normally
9849         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9850         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);
9851         RSurf_DrawBatch();
9852 }
9853
9854 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9855 {
9856         // OpenGL 1.3 path - anything not completely ancient
9857         qboolean applycolor;
9858         qboolean applyfog;
9859         int layerindex;
9860         const texturelayer_t *layer;
9861         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);
9862         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9863
9864         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9865         {
9866                 vec4_t layercolor;
9867                 int layertexrgbscale;
9868                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9869                 {
9870                         if (layerindex == 0)
9871                                 GL_AlphaTest(true);
9872                         else
9873                         {
9874                                 GL_AlphaTest(false);
9875                                 GL_DepthFunc(GL_EQUAL);
9876                         }
9877                 }
9878                 GL_DepthMask(layer->depthmask && writedepth);
9879                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9880                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9881                 {
9882                         layertexrgbscale = 4;
9883                         VectorScale(layer->color, 0.25f, layercolor);
9884                 }
9885                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9886                 {
9887                         layertexrgbscale = 2;
9888                         VectorScale(layer->color, 0.5f, layercolor);
9889                 }
9890                 else
9891                 {
9892                         layertexrgbscale = 1;
9893                         VectorScale(layer->color, 1.0f, layercolor);
9894                 }
9895                 layercolor[3] = layer->color[3];
9896                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9897                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9898                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9899                 switch (layer->type)
9900                 {
9901                 case TEXTURELAYERTYPE_LITTEXTURE:
9902                         // single-pass lightmapped texture with 2x rgbscale
9903                         R_Mesh_TexBind(0, r_texture_white);
9904                         R_Mesh_TexMatrix(0, NULL);
9905                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9906                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9907                         R_Mesh_TexBind(1, layer->texture);
9908                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9909                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9910                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9911                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9912                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9913                         else if (FAKELIGHT_ENABLED)
9914                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9915                         else if (rsurface.uselightmaptexture)
9916                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9917                         else
9918                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9919                         break;
9920                 case TEXTURELAYERTYPE_TEXTURE:
9921                         // singletexture unlit texture with transparency support
9922                         R_Mesh_TexBind(0, layer->texture);
9923                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9924                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9925                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9926                         R_Mesh_TexBind(1, 0);
9927                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9928                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9929                         break;
9930                 case TEXTURELAYERTYPE_FOG:
9931                         // singletexture fogging
9932                         if (layer->texture)
9933                         {
9934                                 R_Mesh_TexBind(0, layer->texture);
9935                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9936                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9937                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9938                         }
9939                         else
9940                         {
9941                                 R_Mesh_TexBind(0, 0);
9942                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9943                         }
9944                         R_Mesh_TexBind(1, 0);
9945                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9946                         // generate a color array for the fog pass
9947                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9948                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9949                         RSurf_DrawBatch();
9950                         break;
9951                 default:
9952                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9953                 }
9954         }
9955         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9956         {
9957                 GL_DepthFunc(GL_LEQUAL);
9958                 GL_AlphaTest(false);
9959         }
9960 }
9961
9962 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9963 {
9964         // OpenGL 1.1 - crusty old voodoo path
9965         qboolean applyfog;
9966         int layerindex;
9967         const texturelayer_t *layer;
9968         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);
9969         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9970
9971         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9972         {
9973                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9974                 {
9975                         if (layerindex == 0)
9976                                 GL_AlphaTest(true);
9977                         else
9978                         {
9979                                 GL_AlphaTest(false);
9980                                 GL_DepthFunc(GL_EQUAL);
9981                         }
9982                 }
9983                 GL_DepthMask(layer->depthmask && writedepth);
9984                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9985                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9986                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9987                 switch (layer->type)
9988                 {
9989                 case TEXTURELAYERTYPE_LITTEXTURE:
9990                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9991                         {
9992                                 // two-pass lit texture with 2x rgbscale
9993                                 // first the lightmap pass
9994                                 R_Mesh_TexBind(0, r_texture_white);
9995                                 R_Mesh_TexMatrix(0, NULL);
9996                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9997                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9998                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9999                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10000                                 else if (FAKELIGHT_ENABLED)
10001                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10002                                 else if (rsurface.uselightmaptexture)
10003                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10004                                 else
10005                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10006                                 // then apply the texture to it
10007                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10008                                 R_Mesh_TexBind(0, layer->texture);
10009                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10010                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10011                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10012                                 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);
10013                         }
10014                         else
10015                         {
10016                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10017                                 R_Mesh_TexBind(0, layer->texture);
10018                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10019                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10020                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10021                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10022                                         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);
10023                                 else
10024                                         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);
10025                         }
10026                         break;
10027                 case TEXTURELAYERTYPE_TEXTURE:
10028                         // singletexture unlit texture with transparency support
10029                         R_Mesh_TexBind(0, layer->texture);
10030                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10031                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10032                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10033                         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);
10034                         break;
10035                 case TEXTURELAYERTYPE_FOG:
10036                         // singletexture fogging
10037                         if (layer->texture)
10038                         {
10039                                 R_Mesh_TexBind(0, layer->texture);
10040                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10041                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10042                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10043                         }
10044                         else
10045                         {
10046                                 R_Mesh_TexBind(0, 0);
10047                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10048                         }
10049                         // generate a color array for the fog pass
10050                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10051                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10052                         RSurf_DrawBatch();
10053                         break;
10054                 default:
10055                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10056                 }
10057         }
10058         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10059         {
10060                 GL_DepthFunc(GL_LEQUAL);
10061                 GL_AlphaTest(false);
10062         }
10063 }
10064
10065 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10066 {
10067         int vi;
10068         int j;
10069         r_vertexgeneric_t *batchvertex;
10070         float c[4];
10071
10072 //      R_Mesh_ResetTextureState();
10073         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10074
10075         if(rsurface.texture && rsurface.texture->currentskinframe)
10076         {
10077                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10078                 c[3] *= rsurface.texture->currentalpha;
10079         }
10080         else
10081         {
10082                 c[0] = 1;
10083                 c[1] = 0;
10084                 c[2] = 1;
10085                 c[3] = 1;
10086         }
10087
10088         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10089         {
10090                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10091                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10092                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10093         }
10094
10095         // brighten it up (as texture value 127 means "unlit")
10096         c[0] *= 2 * r_refdef.view.colorscale;
10097         c[1] *= 2 * r_refdef.view.colorscale;
10098         c[2] *= 2 * r_refdef.view.colorscale;
10099
10100         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10101                 c[3] *= r_wateralpha.value;
10102
10103         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10104         {
10105                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10106                 GL_DepthMask(false);
10107         }
10108         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10109         {
10110                 GL_BlendFunc(GL_ONE, GL_ONE);
10111                 GL_DepthMask(false);
10112         }
10113         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10114         {
10115                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10116                 GL_DepthMask(false);
10117         }
10118         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10119         {
10120                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10121                 GL_DepthMask(false);
10122         }
10123         else
10124         {
10125                 GL_BlendFunc(GL_ONE, GL_ZERO);
10126                 GL_DepthMask(writedepth);
10127         }
10128
10129         if (r_showsurfaces.integer == 3)
10130         {
10131                 rsurface.passcolor4f = NULL;
10132
10133                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10134                 {
10135                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10136
10137                         rsurface.passcolor4f = NULL;
10138                         rsurface.passcolor4f_vertexbuffer = 0;
10139                         rsurface.passcolor4f_bufferoffset = 0;
10140                 }
10141                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10142                 {
10143                         qboolean applycolor = true;
10144                         float one = 1.0;
10145
10146                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10147
10148                         r_refdef.lightmapintensity = 1;
10149                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10150                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10151                 }
10152                 else if (FAKELIGHT_ENABLED)
10153                 {
10154                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10155
10156                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10157                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10158                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10159                 }
10160                 else
10161                 {
10162                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10163
10164                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10165                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10166                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10167                 }
10168
10169                 if(!rsurface.passcolor4f)
10170                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10171
10172                 RSurf_DrawBatch_GL11_ApplyAmbient();
10173                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10174                 if(r_refdef.fogenabled)
10175                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10176                 RSurf_DrawBatch_GL11_ClampColor();
10177
10178                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10179                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10180                 RSurf_DrawBatch();
10181         }
10182         else if (!r_refdef.view.showdebug)
10183         {
10184                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10185                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10186                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10187                 {
10188                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10189                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10190                 }
10191                 R_Mesh_PrepareVertices_Generic_Unlock();
10192                 RSurf_DrawBatch();
10193         }
10194         else if (r_showsurfaces.integer == 4)
10195         {
10196                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10197                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10198                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10199                 {
10200                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10201                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10202                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10203                 }
10204                 R_Mesh_PrepareVertices_Generic_Unlock();
10205                 RSurf_DrawBatch();
10206         }
10207         else if (r_showsurfaces.integer == 2)
10208         {
10209                 const int *e;
10210                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10211                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10212                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10213                 {
10214                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10215                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10216                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10217                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10218                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10219                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10220                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10221                 }
10222                 R_Mesh_PrepareVertices_Generic_Unlock();
10223                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10224         }
10225         else
10226         {
10227                 int texturesurfaceindex;
10228                 int k;
10229                 const msurface_t *surface;
10230                 float surfacecolor4f[4];
10231                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10232                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10233                 vi = 0;
10234                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10235                 {
10236                         surface = texturesurfacelist[texturesurfaceindex];
10237                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10238                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10239                         for (j = 0;j < surface->num_vertices;j++)
10240                         {
10241                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10242                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10243                                 vi++;
10244                         }
10245                 }
10246                 R_Mesh_PrepareVertices_Generic_Unlock();
10247                 RSurf_DrawBatch();
10248         }
10249 }
10250
10251 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10252 {
10253         CHECKGLERROR
10254         RSurf_SetupDepthAndCulling();
10255         if (r_showsurfaces.integer)
10256         {
10257                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10258                 return;
10259         }
10260         switch (vid.renderpath)
10261         {
10262         case RENDERPATH_GL20:
10263         case RENDERPATH_D3D9:
10264         case RENDERPATH_D3D10:
10265         case RENDERPATH_D3D11:
10266         case RENDERPATH_SOFT:
10267         case RENDERPATH_GLES2:
10268                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10269                 break;
10270         case RENDERPATH_GL13:
10271         case RENDERPATH_GLES1:
10272                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10273                 break;
10274         case RENDERPATH_GL11:
10275                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10276                 break;
10277         }
10278         CHECKGLERROR
10279 }
10280
10281 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10282 {
10283         CHECKGLERROR
10284         RSurf_SetupDepthAndCulling();
10285         if (r_showsurfaces.integer)
10286         {
10287                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10288                 return;
10289         }
10290         switch (vid.renderpath)
10291         {
10292         case RENDERPATH_GL20:
10293         case RENDERPATH_D3D9:
10294         case RENDERPATH_D3D10:
10295         case RENDERPATH_D3D11:
10296         case RENDERPATH_SOFT:
10297         case RENDERPATH_GLES2:
10298                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10299                 break;
10300         case RENDERPATH_GL13:
10301         case RENDERPATH_GLES1:
10302                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10303                 break;
10304         case RENDERPATH_GL11:
10305                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10306                 break;
10307         }
10308         CHECKGLERROR
10309 }
10310
10311 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10312 {
10313         int i, j;
10314         int texturenumsurfaces, endsurface;
10315         texture_t *texture;
10316         const msurface_t *surface;
10317         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10318
10319         // if the model is static it doesn't matter what value we give for
10320         // wantnormals and wanttangents, so this logic uses only rules applicable
10321         // to a model, knowing that they are meaningless otherwise
10322         if (ent == r_refdef.scene.worldentity)
10323                 RSurf_ActiveWorldEntity();
10324         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10325                 RSurf_ActiveModelEntity(ent, false, false, false);
10326         else
10327         {
10328                 switch (vid.renderpath)
10329                 {
10330                 case RENDERPATH_GL20:
10331                 case RENDERPATH_D3D9:
10332                 case RENDERPATH_D3D10:
10333                 case RENDERPATH_D3D11:
10334                 case RENDERPATH_SOFT:
10335                 case RENDERPATH_GLES2:
10336                         RSurf_ActiveModelEntity(ent, true, true, false);
10337                         break;
10338                 case RENDERPATH_GL11:
10339                 case RENDERPATH_GL13:
10340                 case RENDERPATH_GLES1:
10341                         RSurf_ActiveModelEntity(ent, true, false, false);
10342                         break;
10343                 }
10344         }
10345
10346         if (r_transparentdepthmasking.integer)
10347         {
10348                 qboolean setup = false;
10349                 for (i = 0;i < numsurfaces;i = j)
10350                 {
10351                         j = i + 1;
10352                         surface = rsurface.modelsurfaces + surfacelist[i];
10353                         texture = surface->texture;
10354                         rsurface.texture = R_GetCurrentTexture(texture);
10355                         rsurface.lightmaptexture = NULL;
10356                         rsurface.deluxemaptexture = NULL;
10357                         rsurface.uselightmaptexture = false;
10358                         // scan ahead until we find a different texture
10359                         endsurface = min(i + 1024, numsurfaces);
10360                         texturenumsurfaces = 0;
10361                         texturesurfacelist[texturenumsurfaces++] = surface;
10362                         for (;j < endsurface;j++)
10363                         {
10364                                 surface = rsurface.modelsurfaces + surfacelist[j];
10365                                 if (texture != surface->texture)
10366                                         break;
10367                                 texturesurfacelist[texturenumsurfaces++] = surface;
10368                         }
10369                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10370                                 continue;
10371                         // render the range of surfaces as depth
10372                         if (!setup)
10373                         {
10374                                 setup = true;
10375                                 GL_ColorMask(0,0,0,0);
10376                                 GL_Color(1,1,1,1);
10377                                 GL_DepthTest(true);
10378                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10379                                 GL_DepthMask(true);
10380 //                              R_Mesh_ResetTextureState();
10381                                 R_SetupShader_DepthOrShadow(false);
10382                         }
10383                         RSurf_SetupDepthAndCulling();
10384                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10385                         if (rsurface.batchvertex3fbuffer)
10386                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10387                         else
10388                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10389                         RSurf_DrawBatch();
10390                 }
10391                 if (setup)
10392                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10393         }
10394
10395         for (i = 0;i < numsurfaces;i = j)
10396         {
10397                 j = i + 1;
10398                 surface = rsurface.modelsurfaces + surfacelist[i];
10399                 texture = surface->texture;
10400                 rsurface.texture = R_GetCurrentTexture(texture);
10401                 // scan ahead until we find a different texture
10402                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10403                 texturenumsurfaces = 0;
10404                 texturesurfacelist[texturenumsurfaces++] = surface;
10405                 if(FAKELIGHT_ENABLED)
10406                 {
10407                         rsurface.lightmaptexture = NULL;
10408                         rsurface.deluxemaptexture = NULL;
10409                         rsurface.uselightmaptexture = false;
10410                         for (;j < endsurface;j++)
10411                         {
10412                                 surface = rsurface.modelsurfaces + surfacelist[j];
10413                                 if (texture != surface->texture)
10414                                         break;
10415                                 texturesurfacelist[texturenumsurfaces++] = surface;
10416                         }
10417                 }
10418                 else
10419                 {
10420                         rsurface.lightmaptexture = surface->lightmaptexture;
10421                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10422                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10423                         for (;j < endsurface;j++)
10424                         {
10425                                 surface = rsurface.modelsurfaces + surfacelist[j];
10426                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10427                                         break;
10428                                 texturesurfacelist[texturenumsurfaces++] = surface;
10429                         }
10430                 }
10431                 // render the range of surfaces
10432                 if (ent == r_refdef.scene.worldentity)
10433                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10434                 else
10435                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10436         }
10437         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10438 }
10439
10440 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10441 {
10442         // transparent surfaces get pushed off into the transparent queue
10443         int surfacelistindex;
10444         const msurface_t *surface;
10445         vec3_t tempcenter, center;
10446         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10447         {
10448                 surface = texturesurfacelist[surfacelistindex];
10449                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10450                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10451                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10452                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10453                 if (queueentity->transparent_offset) // transparent offset
10454                 {
10455                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10456                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10457                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10458                 }
10459                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10460         }
10461 }
10462
10463 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10464 {
10465         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10466                 return;
10467         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10468                 return;
10469         RSurf_SetupDepthAndCulling();
10470         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10471         if (rsurface.batchvertex3fbuffer)
10472                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10473         else
10474                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10475         RSurf_DrawBatch();
10476 }
10477
10478 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10479 {
10480         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10481         CHECKGLERROR
10482         if (depthonly)
10483                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10484         else if (prepass)
10485         {
10486                 if (!rsurface.texture->currentnumlayers)
10487                         return;
10488                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10489                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10490                 else
10491                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10492         }
10493         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10494                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10495         else if (!rsurface.texture->currentnumlayers)
10496                 return;
10497         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10498         {
10499                 // in the deferred case, transparent surfaces were queued during prepass
10500                 if (!r_shadow_usingdeferredprepass)
10501                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10502         }
10503         else
10504         {
10505                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10506                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10507         }
10508         CHECKGLERROR
10509 }
10510
10511 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10512 {
10513         int i, j;
10514         texture_t *texture;
10515         R_FrameData_SetMark();
10516         // break the surface list down into batches by texture and use of lightmapping
10517         for (i = 0;i < numsurfaces;i = j)
10518         {
10519                 j = i + 1;
10520                 // texture is the base texture pointer, rsurface.texture is the
10521                 // current frame/skin the texture is directing us to use (for example
10522                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10523                 // use skin 1 instead)
10524                 texture = surfacelist[i]->texture;
10525                 rsurface.texture = R_GetCurrentTexture(texture);
10526                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10527                 {
10528                         // if this texture is not the kind we want, skip ahead to the next one
10529                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10530                                 ;
10531                         continue;
10532                 }
10533                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10534                 {
10535                         rsurface.lightmaptexture = NULL;
10536                         rsurface.deluxemaptexture = NULL;
10537                         rsurface.uselightmaptexture = false;
10538                         // simply scan ahead until we find a different texture or lightmap state
10539                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10540                                 ;
10541                 }
10542                 else
10543                 {
10544                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10545                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10546                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10547                         // simply scan ahead until we find a different texture or lightmap state
10548                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10549                                 ;
10550                 }
10551                 // render the range of surfaces
10552                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10553         }
10554         R_FrameData_ReturnToMark();
10555 }
10556
10557 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10558 {
10559         CHECKGLERROR
10560         if (depthonly)
10561                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10562         else if (prepass)
10563         {
10564                 if (!rsurface.texture->currentnumlayers)
10565                         return;
10566                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10567                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10568                 else
10569                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10570         }
10571         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10572                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10573         else if (!rsurface.texture->currentnumlayers)
10574                 return;
10575         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10576         {
10577                 // in the deferred case, transparent surfaces were queued during prepass
10578                 if (!r_shadow_usingdeferredprepass)
10579                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10580         }
10581         else
10582         {
10583                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10584                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10585         }
10586         CHECKGLERROR
10587 }
10588
10589 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10590 {
10591         int i, j;
10592         texture_t *texture;
10593         R_FrameData_SetMark();
10594         // break the surface list down into batches by texture and use of lightmapping
10595         for (i = 0;i < numsurfaces;i = j)
10596         {
10597                 j = i + 1;
10598                 // texture is the base texture pointer, rsurface.texture is the
10599                 // current frame/skin the texture is directing us to use (for example
10600                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10601                 // use skin 1 instead)
10602                 texture = surfacelist[i]->texture;
10603                 rsurface.texture = R_GetCurrentTexture(texture);
10604                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10605                 {
10606                         // if this texture is not the kind we want, skip ahead to the next one
10607                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10608                                 ;
10609                         continue;
10610                 }
10611                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10612                 {
10613                         rsurface.lightmaptexture = NULL;
10614                         rsurface.deluxemaptexture = NULL;
10615                         rsurface.uselightmaptexture = false;
10616                         // simply scan ahead until we find a different texture or lightmap state
10617                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10618                                 ;
10619                 }
10620                 else
10621                 {
10622                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10623                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10624                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10625                         // simply scan ahead until we find a different texture or lightmap state
10626                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10627                                 ;
10628                 }
10629                 // render the range of surfaces
10630                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10631         }
10632         R_FrameData_ReturnToMark();
10633 }
10634
10635 float locboxvertex3f[6*4*3] =
10636 {
10637         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10638         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10639         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10640         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10641         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10642         1,0,0, 0,0,0, 0,1,0, 1,1,0
10643 };
10644
10645 unsigned short locboxelements[6*2*3] =
10646 {
10647          0, 1, 2, 0, 2, 3,
10648          4, 5, 6, 4, 6, 7,
10649          8, 9,10, 8,10,11,
10650         12,13,14, 12,14,15,
10651         16,17,18, 16,18,19,
10652         20,21,22, 20,22,23
10653 };
10654
10655 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10656 {
10657         int i, j;
10658         cl_locnode_t *loc = (cl_locnode_t *)ent;
10659         vec3_t mins, size;
10660         float vertex3f[6*4*3];
10661         CHECKGLERROR
10662         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10663         GL_DepthMask(false);
10664         GL_DepthRange(0, 1);
10665         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10666         GL_DepthTest(true);
10667         GL_CullFace(GL_NONE);
10668         R_EntityMatrix(&identitymatrix);
10669
10670 //      R_Mesh_ResetTextureState();
10671
10672         i = surfacelist[0];
10673         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10674                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10675                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10676                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10677
10678         if (VectorCompare(loc->mins, loc->maxs))
10679         {
10680                 VectorSet(size, 2, 2, 2);
10681                 VectorMA(loc->mins, -0.5f, size, mins);
10682         }
10683         else
10684         {
10685                 VectorCopy(loc->mins, mins);
10686                 VectorSubtract(loc->maxs, loc->mins, size);
10687         }
10688
10689         for (i = 0;i < 6*4*3;)
10690                 for (j = 0;j < 3;j++, i++)
10691                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10692
10693         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10694         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10695         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10696 }
10697
10698 void R_DrawLocs(void)
10699 {
10700         int index;
10701         cl_locnode_t *loc, *nearestloc;
10702         vec3_t center;
10703         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10704         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10705         {
10706                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10707                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10708         }
10709 }
10710
10711 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10712 {
10713         if (decalsystem->decals)
10714                 Mem_Free(decalsystem->decals);
10715         memset(decalsystem, 0, sizeof(*decalsystem));
10716 }
10717
10718 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)
10719 {
10720         tridecal_t *decal;
10721         tridecal_t *decals;
10722         int i;
10723
10724         // expand or initialize the system
10725         if (decalsystem->maxdecals <= decalsystem->numdecals)
10726         {
10727                 decalsystem_t old = *decalsystem;
10728                 qboolean useshortelements;
10729                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10730                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10731                 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)));
10732                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10733                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10734                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10735                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10736                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10737                 if (decalsystem->numdecals)
10738                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10739                 if (old.decals)
10740                         Mem_Free(old.decals);
10741                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10742                         decalsystem->element3i[i] = i;
10743                 if (useshortelements)
10744                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10745                                 decalsystem->element3s[i] = i;
10746         }
10747
10748         // grab a decal and search for another free slot for the next one
10749         decals = decalsystem->decals;
10750         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10751         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10752                 ;
10753         decalsystem->freedecal = i;
10754         if (decalsystem->numdecals <= i)
10755                 decalsystem->numdecals = i + 1;
10756
10757         // initialize the decal
10758         decal->lived = 0;
10759         decal->triangleindex = triangleindex;
10760         decal->surfaceindex = surfaceindex;
10761         decal->decalsequence = decalsequence;
10762         decal->color4f[0][0] = c0[0];
10763         decal->color4f[0][1] = c0[1];
10764         decal->color4f[0][2] = c0[2];
10765         decal->color4f[0][3] = 1;
10766         decal->color4f[1][0] = c1[0];
10767         decal->color4f[1][1] = c1[1];
10768         decal->color4f[1][2] = c1[2];
10769         decal->color4f[1][3] = 1;
10770         decal->color4f[2][0] = c2[0];
10771         decal->color4f[2][1] = c2[1];
10772         decal->color4f[2][2] = c2[2];
10773         decal->color4f[2][3] = 1;
10774         decal->vertex3f[0][0] = v0[0];
10775         decal->vertex3f[0][1] = v0[1];
10776         decal->vertex3f[0][2] = v0[2];
10777         decal->vertex3f[1][0] = v1[0];
10778         decal->vertex3f[1][1] = v1[1];
10779         decal->vertex3f[1][2] = v1[2];
10780         decal->vertex3f[2][0] = v2[0];
10781         decal->vertex3f[2][1] = v2[1];
10782         decal->vertex3f[2][2] = v2[2];
10783         decal->texcoord2f[0][0] = t0[0];
10784         decal->texcoord2f[0][1] = t0[1];
10785         decal->texcoord2f[1][0] = t1[0];
10786         decal->texcoord2f[1][1] = t1[1];
10787         decal->texcoord2f[2][0] = t2[0];
10788         decal->texcoord2f[2][1] = t2[1];
10789         TriangleNormal(v0, v1, v2, decal->plane);
10790         VectorNormalize(decal->plane);
10791         decal->plane[3] = DotProduct(v0, decal->plane);
10792 }
10793
10794 extern cvar_t cl_decals_bias;
10795 extern cvar_t cl_decals_models;
10796 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10797 // baseparms, parms, temps
10798 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)
10799 {
10800         int cornerindex;
10801         int index;
10802         float v[9][3];
10803         const float *vertex3f;
10804         const float *normal3f;
10805         int numpoints;
10806         float points[2][9][3];
10807         float temp[3];
10808         float tc[9][2];
10809         float f;
10810         float c[9][4];
10811         const int *e;
10812
10813         e = rsurface.modelelement3i + 3*triangleindex;
10814
10815         vertex3f = rsurface.modelvertex3f;
10816         normal3f = rsurface.modelnormal3f;
10817
10818         if (normal3f)
10819         {
10820                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10821                 {
10822                         index = 3*e[cornerindex];
10823                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10824                 }
10825         }
10826         else
10827         {
10828                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10829                 {
10830                         index = 3*e[cornerindex];
10831                         VectorCopy(vertex3f + index, v[cornerindex]);
10832                 }
10833         }
10834
10835         // cull backfaces
10836         //TriangleNormal(v[0], v[1], v[2], normal);
10837         //if (DotProduct(normal, localnormal) < 0.0f)
10838         //      continue;
10839         // clip by each of the box planes formed from the projection matrix
10840         // if anything survives, we emit the decal
10841         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]);
10842         if (numpoints < 3)
10843                 return;
10844         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]);
10845         if (numpoints < 3)
10846                 return;
10847         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]);
10848         if (numpoints < 3)
10849                 return;
10850         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]);
10851         if (numpoints < 3)
10852                 return;
10853         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]);
10854         if (numpoints < 3)
10855                 return;
10856         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]);
10857         if (numpoints < 3)
10858                 return;
10859         // some part of the triangle survived, so we have to accept it...
10860         if (dynamic)
10861         {
10862                 // dynamic always uses the original triangle
10863                 numpoints = 3;
10864                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10865                 {
10866                         index = 3*e[cornerindex];
10867                         VectorCopy(vertex3f + index, v[cornerindex]);
10868                 }
10869         }
10870         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10871         {
10872                 // convert vertex positions to texcoords
10873                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10874                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10875                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10876                 // calculate distance fade from the projection origin
10877                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10878                 f = bound(0.0f, f, 1.0f);
10879                 c[cornerindex][0] = r * f;
10880                 c[cornerindex][1] = g * f;
10881                 c[cornerindex][2] = b * f;
10882                 c[cornerindex][3] = 1.0f;
10883                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10884         }
10885         if (dynamic)
10886                 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);
10887         else
10888                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10889                         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);
10890 }
10891 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)
10892 {
10893         matrix4x4_t projection;
10894         decalsystem_t *decalsystem;
10895         qboolean dynamic;
10896         dp_model_t *model;
10897         const msurface_t *surface;
10898         const msurface_t *surfaces;
10899         const int *surfacelist;
10900         const texture_t *texture;
10901         int numtriangles;
10902         int numsurfacelist;
10903         int surfacelistindex;
10904         int surfaceindex;
10905         int triangleindex;
10906         float localorigin[3];
10907         float localnormal[3];
10908         float localmins[3];
10909         float localmaxs[3];
10910         float localsize;
10911         //float normal[3];
10912         float planes[6][4];
10913         float angles[3];
10914         bih_t *bih;
10915         int bih_triangles_count;
10916         int bih_triangles[256];
10917         int bih_surfaces[256];
10918
10919         decalsystem = &ent->decalsystem;
10920         model = ent->model;
10921         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10922         {
10923                 R_DecalSystem_Reset(&ent->decalsystem);
10924                 return;
10925         }
10926
10927         if (!model->brush.data_leafs && !cl_decals_models.integer)
10928         {
10929                 if (decalsystem->model)
10930                         R_DecalSystem_Reset(decalsystem);
10931                 return;
10932         }
10933
10934         if (decalsystem->model != model)
10935                 R_DecalSystem_Reset(decalsystem);
10936         decalsystem->model = model;
10937
10938         RSurf_ActiveModelEntity(ent, true, false, false);
10939
10940         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10941         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10942         VectorNormalize(localnormal);
10943         localsize = worldsize*rsurface.inversematrixscale;
10944         localmins[0] = localorigin[0] - localsize;
10945         localmins[1] = localorigin[1] - localsize;
10946         localmins[2] = localorigin[2] - localsize;
10947         localmaxs[0] = localorigin[0] + localsize;
10948         localmaxs[1] = localorigin[1] + localsize;
10949         localmaxs[2] = localorigin[2] + localsize;
10950
10951         //VectorCopy(localnormal, planes[4]);
10952         //VectorVectors(planes[4], planes[2], planes[0]);
10953         AnglesFromVectors(angles, localnormal, NULL, false);
10954         AngleVectors(angles, planes[0], planes[2], planes[4]);
10955         VectorNegate(planes[0], planes[1]);
10956         VectorNegate(planes[2], planes[3]);
10957         VectorNegate(planes[4], planes[5]);
10958         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10959         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10960         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10961         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10962         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10963         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10964
10965 #if 1
10966 // works
10967 {
10968         matrix4x4_t forwardprojection;
10969         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10970         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10971 }
10972 #else
10973 // broken
10974 {
10975         float projectionvector[4][3];
10976         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10977         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10978         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10979         projectionvector[0][0] = planes[0][0] * ilocalsize;
10980         projectionvector[0][1] = planes[1][0] * ilocalsize;
10981         projectionvector[0][2] = planes[2][0] * ilocalsize;
10982         projectionvector[1][0] = planes[0][1] * ilocalsize;
10983         projectionvector[1][1] = planes[1][1] * ilocalsize;
10984         projectionvector[1][2] = planes[2][1] * ilocalsize;
10985         projectionvector[2][0] = planes[0][2] * ilocalsize;
10986         projectionvector[2][1] = planes[1][2] * ilocalsize;
10987         projectionvector[2][2] = planes[2][2] * ilocalsize;
10988         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10989         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10990         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10991         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10992 }
10993 #endif
10994
10995         dynamic = model->surfmesh.isanimated;
10996         numsurfacelist = model->nummodelsurfaces;
10997         surfacelist = model->sortedmodelsurfaces;
10998         surfaces = model->data_surfaces;
10999
11000         bih = NULL;
11001         bih_triangles_count = -1;
11002         if(!dynamic)
11003         {
11004                 if(model->render_bih.numleafs)
11005                         bih = &model->render_bih;
11006                 else if(model->collision_bih.numleafs)
11007                         bih = &model->collision_bih;
11008         }
11009         if(bih)
11010                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11011         if(bih_triangles_count == 0)
11012                 return;
11013         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11014                 return;
11015         if(bih_triangles_count > 0)
11016         {
11017                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11018                 {
11019                         surfaceindex = bih_surfaces[triangleindex];
11020                         surface = surfaces + surfaceindex;
11021                         texture = surface->texture;
11022                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11023                                 continue;
11024                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11025                                 continue;
11026                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11027                 }
11028         }
11029         else
11030         {
11031                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11032                 {
11033                         surfaceindex = surfacelist[surfacelistindex];
11034                         surface = surfaces + surfaceindex;
11035                         // check cull box first because it rejects more than any other check
11036                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11037                                 continue;
11038                         // skip transparent surfaces
11039                         texture = surface->texture;
11040                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11041                                 continue;
11042                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11043                                 continue;
11044                         numtriangles = surface->num_triangles;
11045                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11046                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11047                 }
11048         }
11049 }
11050
11051 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11052 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)
11053 {
11054         int renderentityindex;
11055         float worldmins[3];
11056         float worldmaxs[3];
11057         entity_render_t *ent;
11058
11059         if (!cl_decals_newsystem.integer)
11060                 return;
11061
11062         worldmins[0] = worldorigin[0] - worldsize;
11063         worldmins[1] = worldorigin[1] - worldsize;
11064         worldmins[2] = worldorigin[2] - worldsize;
11065         worldmaxs[0] = worldorigin[0] + worldsize;
11066         worldmaxs[1] = worldorigin[1] + worldsize;
11067         worldmaxs[2] = worldorigin[2] + worldsize;
11068
11069         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11070
11071         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11072         {
11073                 ent = r_refdef.scene.entities[renderentityindex];
11074                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11075                         continue;
11076
11077                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11078         }
11079 }
11080
11081 typedef struct r_decalsystem_splatqueue_s
11082 {
11083         vec3_t worldorigin;
11084         vec3_t worldnormal;
11085         float color[4];
11086         float tcrange[4];
11087         float worldsize;
11088         int decalsequence;
11089 }
11090 r_decalsystem_splatqueue_t;
11091
11092 int r_decalsystem_numqueued = 0;
11093 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11094
11095 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)
11096 {
11097         r_decalsystem_splatqueue_t *queue;
11098
11099         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11100                 return;
11101
11102         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11103         VectorCopy(worldorigin, queue->worldorigin);
11104         VectorCopy(worldnormal, queue->worldnormal);
11105         Vector4Set(queue->color, r, g, b, a);
11106         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11107         queue->worldsize = worldsize;
11108         queue->decalsequence = cl.decalsequence++;
11109 }
11110
11111 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11112 {
11113         int i;
11114         r_decalsystem_splatqueue_t *queue;
11115
11116         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11117                 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);
11118         r_decalsystem_numqueued = 0;
11119 }
11120
11121 extern cvar_t cl_decals_max;
11122 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11123 {
11124         int i;
11125         decalsystem_t *decalsystem = &ent->decalsystem;
11126         int numdecals;
11127         int killsequence;
11128         tridecal_t *decal;
11129         float frametime;
11130         float lifetime;
11131
11132         if (!decalsystem->numdecals)
11133                 return;
11134
11135         if (r_showsurfaces.integer)
11136                 return;
11137
11138         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11139         {
11140                 R_DecalSystem_Reset(decalsystem);
11141                 return;
11142         }
11143
11144         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11145         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11146
11147         if (decalsystem->lastupdatetime)
11148                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11149         else
11150                 frametime = 0;
11151         decalsystem->lastupdatetime = r_refdef.scene.time;
11152         decal = decalsystem->decals;
11153         numdecals = decalsystem->numdecals;
11154
11155         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11156         {
11157                 if (decal->color4f[0][3])
11158                 {
11159                         decal->lived += frametime;
11160                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11161                         {
11162                                 memset(decal, 0, sizeof(*decal));
11163                                 if (decalsystem->freedecal > i)
11164                                         decalsystem->freedecal = i;
11165                         }
11166                 }
11167         }
11168         decal = decalsystem->decals;
11169         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11170                 numdecals--;
11171
11172         // collapse the array by shuffling the tail decals into the gaps
11173         for (;;)
11174         {
11175                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11176                         decalsystem->freedecal++;
11177                 if (decalsystem->freedecal == numdecals)
11178                         break;
11179                 decal[decalsystem->freedecal] = decal[--numdecals];
11180         }
11181
11182         decalsystem->numdecals = numdecals;
11183
11184         if (numdecals <= 0)
11185         {
11186                 // if there are no decals left, reset decalsystem
11187                 R_DecalSystem_Reset(decalsystem);
11188         }
11189 }
11190
11191 extern skinframe_t *decalskinframe;
11192 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11193 {
11194         int i;
11195         decalsystem_t *decalsystem = &ent->decalsystem;
11196         int numdecals;
11197         tridecal_t *decal;
11198         float faderate;
11199         float alpha;
11200         float *v3f;
11201         float *c4f;
11202         float *t2f;
11203         const int *e;
11204         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11205         int numtris = 0;
11206
11207         numdecals = decalsystem->numdecals;
11208         if (!numdecals)
11209                 return;
11210
11211         if (r_showsurfaces.integer)
11212                 return;
11213
11214         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11215         {
11216                 R_DecalSystem_Reset(decalsystem);
11217                 return;
11218         }
11219
11220         // if the model is static it doesn't matter what value we give for
11221         // wantnormals and wanttangents, so this logic uses only rules applicable
11222         // to a model, knowing that they are meaningless otherwise
11223         if (ent == r_refdef.scene.worldentity)
11224                 RSurf_ActiveWorldEntity();
11225         else
11226                 RSurf_ActiveModelEntity(ent, false, false, false);
11227
11228         decalsystem->lastupdatetime = r_refdef.scene.time;
11229         decal = decalsystem->decals;
11230
11231         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11232
11233         // update vertex positions for animated models
11234         v3f = decalsystem->vertex3f;
11235         c4f = decalsystem->color4f;
11236         t2f = decalsystem->texcoord2f;
11237         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11238         {
11239                 if (!decal->color4f[0][3])
11240                         continue;
11241
11242                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11243                         continue;
11244
11245                 // skip backfaces
11246                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11247                         continue;
11248
11249                 // update color values for fading decals
11250                 if (decal->lived >= cl_decals_time.value)
11251                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11252                 else
11253                         alpha = 1.0f;
11254
11255                 c4f[ 0] = decal->color4f[0][0] * alpha;
11256                 c4f[ 1] = decal->color4f[0][1] * alpha;
11257                 c4f[ 2] = decal->color4f[0][2] * alpha;
11258                 c4f[ 3] = 1;
11259                 c4f[ 4] = decal->color4f[1][0] * alpha;
11260                 c4f[ 5] = decal->color4f[1][1] * alpha;
11261                 c4f[ 6] = decal->color4f[1][2] * alpha;
11262                 c4f[ 7] = 1;
11263                 c4f[ 8] = decal->color4f[2][0] * alpha;
11264                 c4f[ 9] = decal->color4f[2][1] * alpha;
11265                 c4f[10] = decal->color4f[2][2] * alpha;
11266                 c4f[11] = 1;
11267
11268                 t2f[0] = decal->texcoord2f[0][0];
11269                 t2f[1] = decal->texcoord2f[0][1];
11270                 t2f[2] = decal->texcoord2f[1][0];
11271                 t2f[3] = decal->texcoord2f[1][1];
11272                 t2f[4] = decal->texcoord2f[2][0];
11273                 t2f[5] = decal->texcoord2f[2][1];
11274
11275                 // update vertex positions for animated models
11276                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11277                 {
11278                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11279                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11280                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11281                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11282                 }
11283                 else
11284                 {
11285                         VectorCopy(decal->vertex3f[0], v3f);
11286                         VectorCopy(decal->vertex3f[1], v3f + 3);
11287                         VectorCopy(decal->vertex3f[2], v3f + 6);
11288                 }
11289
11290                 if (r_refdef.fogenabled)
11291                 {
11292                         alpha = RSurf_FogVertex(v3f);
11293                         VectorScale(c4f, alpha, c4f);
11294                         alpha = RSurf_FogVertex(v3f + 3);
11295                         VectorScale(c4f + 4, alpha, c4f + 4);
11296                         alpha = RSurf_FogVertex(v3f + 6);
11297                         VectorScale(c4f + 8, alpha, c4f + 8);
11298                 }
11299
11300                 v3f += 9;
11301                 c4f += 12;
11302                 t2f += 6;
11303                 numtris++;
11304         }
11305
11306         if (numtris > 0)
11307         {
11308                 r_refdef.stats.drawndecals += numtris;
11309
11310                 // now render the decals all at once
11311                 // (this assumes they all use one particle font texture!)
11312                 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);
11313 //              R_Mesh_ResetTextureState();
11314                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11315                 GL_DepthMask(false);
11316                 GL_DepthRange(0, 1);
11317                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11318                 GL_DepthTest(true);
11319                 GL_CullFace(GL_NONE);
11320                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11321                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11322                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11323         }
11324 }
11325
11326 static void R_DrawModelDecals(void)
11327 {
11328         int i, numdecals;
11329
11330         // fade faster when there are too many decals
11331         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11332         for (i = 0;i < r_refdef.scene.numentities;i++)
11333                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11334
11335         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11336         for (i = 0;i < r_refdef.scene.numentities;i++)
11337                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11338                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11339
11340         R_DecalSystem_ApplySplatEntitiesQueue();
11341
11342         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11343         for (i = 0;i < r_refdef.scene.numentities;i++)
11344                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11345
11346         r_refdef.stats.totaldecals += numdecals;
11347
11348         if (r_showsurfaces.integer)
11349                 return;
11350
11351         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11352
11353         for (i = 0;i < r_refdef.scene.numentities;i++)
11354         {
11355                 if (!r_refdef.viewcache.entityvisible[i])
11356                         continue;
11357                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11358                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11359         }
11360 }
11361
11362 extern cvar_t mod_collision_bih;
11363 void R_DrawDebugModel(void)
11364 {
11365         entity_render_t *ent = rsurface.entity;
11366         int i, j, k, l, flagsmask;
11367         const msurface_t *surface;
11368         dp_model_t *model = ent->model;
11369         vec3_t v;
11370
11371         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11372                 return;
11373
11374         if (r_showoverdraw.value > 0)
11375         {
11376                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11377                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11378                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11379                 GL_DepthTest(false);
11380                 GL_DepthMask(false);
11381                 GL_DepthRange(0, 1);
11382                 GL_BlendFunc(GL_ONE, GL_ONE);
11383                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11384                 {
11385                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11386                                 continue;
11387                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11388                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11389                         {
11390                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11391                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11392                                 if (!rsurface.texture->currentlayers->depthmask)
11393                                         GL_Color(c, 0, 0, 1.0f);
11394                                 else if (ent == r_refdef.scene.worldentity)
11395                                         GL_Color(c, c, c, 1.0f);
11396                                 else
11397                                         GL_Color(0, c, 0, 1.0f);
11398                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11399                                 RSurf_DrawBatch();
11400                         }
11401                 }
11402                 rsurface.texture = NULL;
11403         }
11404
11405         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11406
11407 //      R_Mesh_ResetTextureState();
11408         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11409         GL_DepthRange(0, 1);
11410         GL_DepthTest(!r_showdisabledepthtest.integer);
11411         GL_DepthMask(false);
11412         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11413
11414         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11415         {
11416                 int triangleindex;
11417                 int bihleafindex;
11418                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11419                 const q3mbrush_t *brush;
11420                 const bih_t *bih = &model->collision_bih;
11421                 const bih_leaf_t *bihleaf;
11422                 float vertex3f[3][3];
11423                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11424                 cullbox = false;
11425                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11426                 {
11427                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11428                                 continue;
11429                         switch (bihleaf->type)
11430                         {
11431                         case BIH_BRUSH:
11432                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11433                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11434                                 {
11435                                         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);
11436                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11437                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11438                                 }
11439                                 break;
11440                         case BIH_COLLISIONTRIANGLE:
11441                                 triangleindex = bihleaf->itemindex;
11442                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11443                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11444                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11445                                 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);
11446                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11447                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11448                                 break;
11449                         case BIH_RENDERTRIANGLE:
11450                                 triangleindex = bihleaf->itemindex;
11451                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11452                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11453                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11454                                 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);
11455                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11456                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11457                                 break;
11458                         }
11459                 }
11460         }
11461
11462         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11463
11464 #ifndef USE_GLES2
11465         if (r_showtris.integer && qglPolygonMode)
11466         {
11467                 if (r_showdisabledepthtest.integer)
11468                 {
11469                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11470                         GL_DepthMask(false);
11471                 }
11472                 else
11473                 {
11474                         GL_BlendFunc(GL_ONE, GL_ZERO);
11475                         GL_DepthMask(true);
11476                 }
11477                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11478                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11479                 {
11480                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11481                                 continue;
11482                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11483                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11484                         {
11485                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11486                                 if (!rsurface.texture->currentlayers->depthmask)
11487                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11488                                 else if (ent == r_refdef.scene.worldentity)
11489                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11490                                 else
11491                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11492                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11493                                 RSurf_DrawBatch();
11494                         }
11495                 }
11496                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11497                 rsurface.texture = NULL;
11498         }
11499
11500         if (r_shownormals.value != 0 && qglBegin)
11501         {
11502                 if (r_showdisabledepthtest.integer)
11503                 {
11504                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11505                         GL_DepthMask(false);
11506                 }
11507                 else
11508                 {
11509                         GL_BlendFunc(GL_ONE, GL_ZERO);
11510                         GL_DepthMask(true);
11511                 }
11512                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11513                 {
11514                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11515                                 continue;
11516                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11517                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11518                         {
11519                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11520                                 qglBegin(GL_LINES);
11521                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11522                                 {
11523                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11524                                         {
11525                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11526                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11527                                                 qglVertex3f(v[0], v[1], v[2]);
11528                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11529                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11530                                                 qglVertex3f(v[0], v[1], v[2]);
11531                                         }
11532                                 }
11533                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11534                                 {
11535                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11536                                         {
11537                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11538                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11539                                                 qglVertex3f(v[0], v[1], v[2]);
11540                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11541                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11542                                                 qglVertex3f(v[0], v[1], v[2]);
11543                                         }
11544                                 }
11545                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11546                                 {
11547                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11548                                         {
11549                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11550                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11551                                                 qglVertex3f(v[0], v[1], v[2]);
11552                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11553                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11554                                                 qglVertex3f(v[0], v[1], v[2]);
11555                                         }
11556                                 }
11557                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11558                                 {
11559                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11560                                         {
11561                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11562                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11563                                                 qglVertex3f(v[0], v[1], v[2]);
11564                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11565                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11566                                                 qglVertex3f(v[0], v[1], v[2]);
11567                                         }
11568                                 }
11569                                 qglEnd();
11570                                 CHECKGLERROR
11571                         }
11572                 }
11573                 rsurface.texture = NULL;
11574         }
11575 #endif
11576 }
11577
11578 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11579 int r_maxsurfacelist = 0;
11580 const msurface_t **r_surfacelist = NULL;
11581 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11582 {
11583         int i, j, endj, flagsmask;
11584         dp_model_t *model = r_refdef.scene.worldmodel;
11585         msurface_t *surfaces;
11586         unsigned char *update;
11587         int numsurfacelist = 0;
11588         if (model == NULL)
11589                 return;
11590
11591         if (r_maxsurfacelist < model->num_surfaces)
11592         {
11593                 r_maxsurfacelist = model->num_surfaces;
11594                 if (r_surfacelist)
11595                         Mem_Free((msurface_t**)r_surfacelist);
11596                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11597         }
11598
11599         RSurf_ActiveWorldEntity();
11600
11601         surfaces = model->data_surfaces;
11602         update = model->brushq1.lightmapupdateflags;
11603
11604         // update light styles on this submodel
11605         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11606         {
11607                 model_brush_lightstyleinfo_t *style;
11608                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11609                 {
11610                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11611                         {
11612                                 int *list = style->surfacelist;
11613                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11614                                 for (j = 0;j < style->numsurfaces;j++)
11615                                         update[list[j]] = true;
11616                         }
11617                 }
11618         }
11619
11620         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11621
11622         if (debug)
11623         {
11624                 R_DrawDebugModel();
11625                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11626                 return;
11627         }
11628
11629         rsurface.lightmaptexture = NULL;
11630         rsurface.deluxemaptexture = NULL;
11631         rsurface.uselightmaptexture = false;
11632         rsurface.texture = NULL;
11633         rsurface.rtlight = NULL;
11634         numsurfacelist = 0;
11635         // add visible surfaces to draw list
11636         for (i = 0;i < model->nummodelsurfaces;i++)
11637         {
11638                 j = model->sortedmodelsurfaces[i];
11639                 if (r_refdef.viewcache.world_surfacevisible[j])
11640                         r_surfacelist[numsurfacelist++] = surfaces + j;
11641         }
11642         // update lightmaps if needed
11643         if (model->brushq1.firstrender)
11644         {
11645                 model->brushq1.firstrender = false;
11646                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11647                         if (update[j])
11648                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11649         }
11650         else if (update)
11651         {
11652                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11653                         if (r_refdef.viewcache.world_surfacevisible[j])
11654                                 if (update[j])
11655                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11656         }
11657         // don't do anything if there were no surfaces
11658         if (!numsurfacelist)
11659         {
11660                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11661                 return;
11662         }
11663         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11664
11665         // add to stats if desired
11666         if (r_speeds.integer && !skysurfaces && !depthonly)
11667         {
11668                 r_refdef.stats.world_surfaces += numsurfacelist;
11669                 for (j = 0;j < numsurfacelist;j++)
11670                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11671         }
11672
11673         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11674 }
11675
11676 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11677 {
11678         int i, j, endj, flagsmask;
11679         dp_model_t *model = ent->model;
11680         msurface_t *surfaces;
11681         unsigned char *update;
11682         int numsurfacelist = 0;
11683         if (model == NULL)
11684                 return;
11685
11686         if (r_maxsurfacelist < model->num_surfaces)
11687         {
11688                 r_maxsurfacelist = model->num_surfaces;
11689                 if (r_surfacelist)
11690                         Mem_Free((msurface_t **)r_surfacelist);
11691                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11692         }
11693
11694         // if the model is static it doesn't matter what value we give for
11695         // wantnormals and wanttangents, so this logic uses only rules applicable
11696         // to a model, knowing that they are meaningless otherwise
11697         if (ent == r_refdef.scene.worldentity)
11698                 RSurf_ActiveWorldEntity();
11699         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11700                 RSurf_ActiveModelEntity(ent, false, false, false);
11701         else if (prepass)
11702                 RSurf_ActiveModelEntity(ent, true, true, true);
11703         else if (depthonly)
11704         {
11705                 switch (vid.renderpath)
11706                 {
11707                 case RENDERPATH_GL20:
11708                 case RENDERPATH_D3D9:
11709                 case RENDERPATH_D3D10:
11710                 case RENDERPATH_D3D11:
11711                 case RENDERPATH_SOFT:
11712                 case RENDERPATH_GLES2:
11713                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11714                         break;
11715                 case RENDERPATH_GL11:
11716                 case RENDERPATH_GL13:
11717                 case RENDERPATH_GLES1:
11718                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11719                         break;
11720                 }
11721         }
11722         else
11723         {
11724                 switch (vid.renderpath)
11725                 {
11726                 case RENDERPATH_GL20:
11727                 case RENDERPATH_D3D9:
11728                 case RENDERPATH_D3D10:
11729                 case RENDERPATH_D3D11:
11730                 case RENDERPATH_SOFT:
11731                 case RENDERPATH_GLES2:
11732                         RSurf_ActiveModelEntity(ent, true, true, false);
11733                         break;
11734                 case RENDERPATH_GL11:
11735                 case RENDERPATH_GL13:
11736                 case RENDERPATH_GLES1:
11737                         RSurf_ActiveModelEntity(ent, true, false, false);
11738                         break;
11739                 }
11740         }
11741
11742         surfaces = model->data_surfaces;
11743         update = model->brushq1.lightmapupdateflags;
11744
11745         // update light styles
11746         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11747         {
11748                 model_brush_lightstyleinfo_t *style;
11749                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11750                 {
11751                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11752                         {
11753                                 int *list = style->surfacelist;
11754                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11755                                 for (j = 0;j < style->numsurfaces;j++)
11756                                         update[list[j]] = true;
11757                         }
11758                 }
11759         }
11760
11761         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11762
11763         if (debug)
11764         {
11765                 R_DrawDebugModel();
11766                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11767                 return;
11768         }
11769
11770         rsurface.lightmaptexture = NULL;
11771         rsurface.deluxemaptexture = NULL;
11772         rsurface.uselightmaptexture = false;
11773         rsurface.texture = NULL;
11774         rsurface.rtlight = NULL;
11775         numsurfacelist = 0;
11776         // add visible surfaces to draw list
11777         for (i = 0;i < model->nummodelsurfaces;i++)
11778                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11779         // don't do anything if there were no surfaces
11780         if (!numsurfacelist)
11781         {
11782                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11783                 return;
11784         }
11785         // update lightmaps if needed
11786         if (update)
11787         {
11788                 int updated = 0;
11789                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11790                 {
11791                         if (update[j])
11792                         {
11793                                 updated++;
11794                                 R_BuildLightMap(ent, surfaces + j);
11795                         }
11796                 }
11797         }
11798         if (update)
11799                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11800                         if (update[j])
11801                                 R_BuildLightMap(ent, surfaces + j);
11802         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11803
11804         // add to stats if desired
11805         if (r_speeds.integer && !skysurfaces && !depthonly)
11806         {
11807                 r_refdef.stats.entities_surfaces += numsurfacelist;
11808                 for (j = 0;j < numsurfacelist;j++)
11809                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11810         }
11811
11812         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11813 }
11814
11815 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11816 {
11817         static texture_t texture;
11818         static msurface_t surface;
11819         const msurface_t *surfacelist = &surface;
11820
11821         // fake enough texture and surface state to render this geometry
11822
11823         texture.update_lastrenderframe = -1; // regenerate this texture
11824         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11825         texture.currentskinframe = skinframe;
11826         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11827         texture.offsetmapping = OFFSETMAPPING_OFF;
11828         texture.offsetscale = 1;
11829         texture.specularscalemod = 1;
11830         texture.specularpowermod = 1;
11831
11832         surface.texture = &texture;
11833         surface.num_triangles = numtriangles;
11834         surface.num_firsttriangle = firsttriangle;
11835         surface.num_vertices = numvertices;
11836         surface.num_firstvertex = firstvertex;
11837
11838         // now render it
11839         rsurface.texture = R_GetCurrentTexture(surface.texture);
11840         rsurface.lightmaptexture = NULL;
11841         rsurface.deluxemaptexture = NULL;
11842         rsurface.uselightmaptexture = false;
11843         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11844 }
11845
11846 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)
11847 {
11848         static msurface_t surface;
11849         const msurface_t *surfacelist = &surface;
11850
11851         // fake enough texture and surface state to render this geometry
11852         surface.texture = texture;
11853         surface.num_triangles = numtriangles;
11854         surface.num_firsttriangle = firsttriangle;
11855         surface.num_vertices = numvertices;
11856         surface.num_firstvertex = firstvertex;
11857
11858         // now render it
11859         rsurface.texture = R_GetCurrentTexture(surface.texture);
11860         rsurface.lightmaptexture = NULL;
11861         rsurface.deluxemaptexture = NULL;
11862         rsurface.uselightmaptexture = false;
11863         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11864 }