]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
1. make the first CSQC rendered view the "main" view, for use e.g. by origin display...
[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 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
187
188 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
189 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
190 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
191 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
192
193 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
194 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
195
196 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
197 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
198 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
199 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
200 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
201
202 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
203 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
204 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
205 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
206 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
207 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
209 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
210 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
211 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
212
213 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
214
215 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
216
217 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
218
219 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
220
221 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
222 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
223
224 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
225
226 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
227
228 extern cvar_t v_glslgamma;
229 extern cvar_t v_glslgamma_2d;
230
231 extern qboolean v_flipped_state;
232
233 r_framebufferstate_t r_fb;
234
235 /// shadow volume bsp struct with automatically growing nodes buffer
236 svbsp_t r_svbsp;
237
238 rtexture_t *r_texture_blanknormalmap;
239 rtexture_t *r_texture_white;
240 rtexture_t *r_texture_grey128;
241 rtexture_t *r_texture_black;
242 rtexture_t *r_texture_notexture;
243 rtexture_t *r_texture_whitecube;
244 rtexture_t *r_texture_normalizationcube;
245 rtexture_t *r_texture_fogattenuation;
246 rtexture_t *r_texture_fogheighttexture;
247 rtexture_t *r_texture_gammaramps;
248 unsigned int r_texture_gammaramps_serial;
249 //rtexture_t *r_texture_fogintensity;
250 rtexture_t *r_texture_reflectcube;
251
252 // TODO: hash lookups?
253 typedef struct cubemapinfo_s
254 {
255         char basename[64];
256         rtexture_t *texture;
257 }
258 cubemapinfo_t;
259
260 int r_texture_numcubemaps;
261 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
262
263 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
264 unsigned int r_numqueries;
265 unsigned int r_maxqueries;
266
267 typedef struct r_qwskincache_s
268 {
269         char name[MAX_QPATH];
270         skinframe_t *skinframe;
271 }
272 r_qwskincache_t;
273
274 static r_qwskincache_t *r_qwskincache;
275 static int r_qwskincache_size;
276
277 /// vertex coordinates for a quad that covers the screen exactly
278 extern const float r_screenvertex3f[12];
279 extern const float r_d3dscreenvertex3f[12];
280 const float r_screenvertex3f[12] =
281 {
282         0, 0, 0,
283         1, 0, 0,
284         1, 1, 0,
285         0, 1, 0
286 };
287 const float r_d3dscreenvertex3f[12] =
288 {
289         0, 1, 0,
290         1, 1, 0,
291         1, 0, 0,
292         0, 0, 0
293 };
294
295 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
296 {
297         int i;
298         for (i = 0;i < verts;i++)
299         {
300                 out[0] = in[0] * r;
301                 out[1] = in[1] * g;
302                 out[2] = in[2] * b;
303                 out[3] = in[3];
304                 in += 4;
305                 out += 4;
306         }
307 }
308
309 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
310 {
311         int i;
312         for (i = 0;i < verts;i++)
313         {
314                 out[0] = r;
315                 out[1] = g;
316                 out[2] = b;
317                 out[3] = a;
318                 out += 4;
319         }
320 }
321
322 // FIXME: move this to client?
323 void FOG_clear(void)
324 {
325         if (gamemode == GAME_NEHAHRA)
326         {
327                 Cvar_Set("gl_fogenable", "0");
328                 Cvar_Set("gl_fogdensity", "0.2");
329                 Cvar_Set("gl_fogred", "0.3");
330                 Cvar_Set("gl_foggreen", "0.3");
331                 Cvar_Set("gl_fogblue", "0.3");
332         }
333         r_refdef.fog_density = 0;
334         r_refdef.fog_red = 0;
335         r_refdef.fog_green = 0;
336         r_refdef.fog_blue = 0;
337         r_refdef.fog_alpha = 1;
338         r_refdef.fog_start = 0;
339         r_refdef.fog_end = 16384;
340         r_refdef.fog_height = 1<<30;
341         r_refdef.fog_fadedepth = 128;
342         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
343 }
344
345 static void R_BuildBlankTextures(void)
346 {
347         unsigned char data[4];
348         data[2] = 128; // normal X
349         data[1] = 128; // normal Y
350         data[0] = 255; // normal Z
351         data[3] = 255; // height
352         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
353         data[0] = 255;
354         data[1] = 255;
355         data[2] = 255;
356         data[3] = 255;
357         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 128;
359         data[1] = 128;
360         data[2] = 128;
361         data[3] = 255;
362         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 0;
364         data[1] = 0;
365         data[2] = 0;
366         data[3] = 255;
367         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368 }
369
370 static void R_BuildNoTexture(void)
371 {
372         int x, y;
373         unsigned char pix[16][16][4];
374         // this makes a light grey/dark grey checkerboard texture
375         for (y = 0;y < 16;y++)
376         {
377                 for (x = 0;x < 16;x++)
378                 {
379                         if ((y < 8) ^ (x < 8))
380                         {
381                                 pix[y][x][0] = 128;
382                                 pix[y][x][1] = 128;
383                                 pix[y][x][2] = 128;
384                                 pix[y][x][3] = 255;
385                         }
386                         else
387                         {
388                                 pix[y][x][0] = 64;
389                                 pix[y][x][1] = 64;
390                                 pix[y][x][2] = 64;
391                                 pix[y][x][3] = 255;
392                         }
393                 }
394         }
395         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
396 }
397
398 static void R_BuildWhiteCube(void)
399 {
400         unsigned char data[6*1*1*4];
401         memset(data, 255, sizeof(data));
402         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNormalizationCube(void)
406 {
407         int x, y, side;
408         vec3_t v;
409         vec_t s, t, intensity;
410 #define NORMSIZE 64
411         unsigned char *data;
412         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
413         for (side = 0;side < 6;side++)
414         {
415                 for (y = 0;y < NORMSIZE;y++)
416                 {
417                         for (x = 0;x < NORMSIZE;x++)
418                         {
419                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
420                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 switch(side)
422                                 {
423                                 default:
424                                 case 0:
425                                         v[0] = 1;
426                                         v[1] = -t;
427                                         v[2] = -s;
428                                         break;
429                                 case 1:
430                                         v[0] = -1;
431                                         v[1] = -t;
432                                         v[2] = s;
433                                         break;
434                                 case 2:
435                                         v[0] = s;
436                                         v[1] = 1;
437                                         v[2] = t;
438                                         break;
439                                 case 3:
440                                         v[0] = s;
441                                         v[1] = -1;
442                                         v[2] = -t;
443                                         break;
444                                 case 4:
445                                         v[0] = s;
446                                         v[1] = -t;
447                                         v[2] = 1;
448                                         break;
449                                 case 5:
450                                         v[0] = -s;
451                                         v[1] = -t;
452                                         v[2] = -1;
453                                         break;
454                                 }
455                                 intensity = 127.0f / sqrt(DotProduct(v, v));
456                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
457                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
458                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
459                                 data[((side*64+y)*64+x)*4+3] = 255;
460                         }
461                 }
462         }
463         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
464         Mem_Free(data);
465 }
466
467 static void R_BuildFogTexture(void)
468 {
469         int x, b;
470 #define FOGWIDTH 256
471         unsigned char data1[FOGWIDTH][4];
472         //unsigned char data2[FOGWIDTH][4];
473         double d, r, alpha;
474
475         r_refdef.fogmasktable_start = r_refdef.fog_start;
476         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
477         r_refdef.fogmasktable_range = r_refdef.fogrange;
478         r_refdef.fogmasktable_density = r_refdef.fog_density;
479
480         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
481         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
482         {
483                 d = (x * r - r_refdef.fogmasktable_start);
484                 if(developer_extra.integer)
485                         Con_DPrintf("%f ", d);
486                 d = max(0, d);
487                 if (r_fog_exp2.integer)
488                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
489                 else
490                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
491                 if(developer_extra.integer)
492                         Con_DPrintf(" : %f ", alpha);
493                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
494                 if(developer_extra.integer)
495                         Con_DPrintf(" = %f\n", alpha);
496                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
497         }
498
499         for (x = 0;x < FOGWIDTH;x++)
500         {
501                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
502                 data1[x][0] = b;
503                 data1[x][1] = b;
504                 data1[x][2] = b;
505                 data1[x][3] = 255;
506                 //data2[x][0] = 255 - b;
507                 //data2[x][1] = 255 - b;
508                 //data2[x][2] = 255 - b;
509                 //data2[x][3] = 255;
510         }
511         if (r_texture_fogattenuation)
512         {
513                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
514                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515         }
516         else
517         {
518                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
519                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
520         }
521 }
522
523 static void R_BuildFogHeightTexture(void)
524 {
525         unsigned char *inpixels;
526         int size;
527         int x;
528         int y;
529         int j;
530         float c[4];
531         float f;
532         inpixels = NULL;
533         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
534         if (r_refdef.fogheighttexturename[0])
535                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
536         if (!inpixels)
537         {
538                 r_refdef.fog_height_tablesize = 0;
539                 if (r_texture_fogheighttexture)
540                         R_FreeTexture(r_texture_fogheighttexture);
541                 r_texture_fogheighttexture = NULL;
542                 if (r_refdef.fog_height_table2d)
543                         Mem_Free(r_refdef.fog_height_table2d);
544                 r_refdef.fog_height_table2d = NULL;
545                 if (r_refdef.fog_height_table1d)
546                         Mem_Free(r_refdef.fog_height_table1d);
547                 r_refdef.fog_height_table1d = NULL;
548                 return;
549         }
550         size = image_width;
551         r_refdef.fog_height_tablesize = size;
552         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
553         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
554         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
555         Mem_Free(inpixels);
556         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
557         // average fog color table accounting for every fog layer between a point
558         // and the camera.  (Note: attenuation is handled separately!)
559         for (y = 0;y < size;y++)
560         {
561                 for (x = 0;x < size;x++)
562                 {
563                         Vector4Clear(c);
564                         f = 0;
565                         if (x < y)
566                         {
567                                 for (j = x;j <= y;j++)
568                                 {
569                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
570                                         f++;
571                                 }
572                         }
573                         else
574                         {
575                                 for (j = x;j >= y;j--)
576                                 {
577                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
578                                         f++;
579                                 }
580                         }
581                         f = 1.0f / f;
582                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
583                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
586                 }
587         }
588         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
589 }
590
591 //=======================================================================================================================================================
592
593 static const char *builtinshaderstring =
594 #include "shader_glsl.h"
595 ;
596
597 const char *builtinhlslshaderstring =
598 #include "shader_hlsl.h"
599 ;
600
601 char *glslshaderstring = NULL;
602 char *hlslshaderstring = NULL;
603
604 //=======================================================================================================================================================
605
606 typedef struct shaderpermutationinfo_s
607 {
608         const char *pretext;
609         const char *name;
610 }
611 shaderpermutationinfo_t;
612
613 typedef struct shadermodeinfo_s
614 {
615         const char *vertexfilename;
616         const char *geometryfilename;
617         const char *fragmentfilename;
618         const char *pretext;
619         const char *name;
620 }
621 shadermodeinfo_t;
622
623 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
624 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
625 {
626         {"#define USEDIFFUSE\n", " diffuse"},
627         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
628         {"#define USEVIEWTINT\n", " viewtint"},
629         {"#define USECOLORMAPPING\n", " colormapping"},
630         {"#define USESATURATION\n", " saturation"},
631         {"#define USEFOGINSIDE\n", " foginside"},
632         {"#define USEFOGOUTSIDE\n", " fogoutside"},
633         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
634         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
635         {"#define USEGAMMARAMPS\n", " gammaramps"},
636         {"#define USECUBEFILTER\n", " cubefilter"},
637         {"#define USEGLOW\n", " glow"},
638         {"#define USEBLOOM\n", " bloom"},
639         {"#define USESPECULAR\n", " specular"},
640         {"#define USEPOSTPROCESSING\n", " postprocessing"},
641         {"#define USEREFLECTION\n", " reflection"},
642         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
643         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
644         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
645         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, // TODO make this a static parm
646         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, // TODO make this a static parm
647         {"#define USESHADOWSAMPLER\n", " shadowsampler"}, // TODO make this a static parm
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656         {"#define USETRIPPY\n", " trippy"},
657 };
658
659 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
660 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
661 {
662         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
663         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
680 };
681
682 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
685         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
702 };
703
704 struct r_glsl_permutation_s;
705 typedef struct r_glsl_permutation_s
706 {
707         /// hash lookup data
708         struct r_glsl_permutation_s *hashnext;
709         unsigned int mode;
710         unsigned int permutation;
711
712         /// indicates if we have tried compiling this permutation already
713         qboolean compiled;
714         /// 0 if compilation failed
715         int program;
716         // texture units assigned to each detected uniform
717         int tex_Texture_First;
718         int tex_Texture_Second;
719         int tex_Texture_GammaRamps;
720         int tex_Texture_Normal;
721         int tex_Texture_Color;
722         int tex_Texture_Gloss;
723         int tex_Texture_Glow;
724         int tex_Texture_SecondaryNormal;
725         int tex_Texture_SecondaryColor;
726         int tex_Texture_SecondaryGloss;
727         int tex_Texture_SecondaryGlow;
728         int tex_Texture_Pants;
729         int tex_Texture_Shirt;
730         int tex_Texture_FogHeightTexture;
731         int tex_Texture_FogMask;
732         int tex_Texture_Lightmap;
733         int tex_Texture_Deluxemap;
734         int tex_Texture_Attenuation;
735         int tex_Texture_Cube;
736         int tex_Texture_Refraction;
737         int tex_Texture_Reflection;
738         int tex_Texture_ShadowMap2D;
739         int tex_Texture_CubeProjection;
740         int tex_Texture_ScreenDepth;
741         int tex_Texture_ScreenNormalMap;
742         int tex_Texture_ScreenDiffuse;
743         int tex_Texture_ScreenSpecular;
744         int tex_Texture_ReflectMask;
745         int tex_Texture_ReflectCube;
746         int tex_Texture_BounceGrid;
747         /// locations of detected uniforms in program object, or -1 if not found
748         int loc_Texture_First;
749         int loc_Texture_Second;
750         int loc_Texture_GammaRamps;
751         int loc_Texture_Normal;
752         int loc_Texture_Color;
753         int loc_Texture_Gloss;
754         int loc_Texture_Glow;
755         int loc_Texture_SecondaryNormal;
756         int loc_Texture_SecondaryColor;
757         int loc_Texture_SecondaryGloss;
758         int loc_Texture_SecondaryGlow;
759         int loc_Texture_Pants;
760         int loc_Texture_Shirt;
761         int loc_Texture_FogHeightTexture;
762         int loc_Texture_FogMask;
763         int loc_Texture_Lightmap;
764         int loc_Texture_Deluxemap;
765         int loc_Texture_Attenuation;
766         int loc_Texture_Cube;
767         int loc_Texture_Refraction;
768         int loc_Texture_Reflection;
769         int loc_Texture_ShadowMap2D;
770         int loc_Texture_CubeProjection;
771         int loc_Texture_ScreenDepth;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1095                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1096                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1097                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1098                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1099                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1100                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1101                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1102                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1103                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1104                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1105                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1106                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1107                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1108                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1109                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1110                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1111                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1112                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1113                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1114                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1115                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1116                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1117                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1118                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1119                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1120                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1121                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1122                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1123                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1124                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1125                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1126                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1127                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1128                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1129                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1130                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1131                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1132                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1133                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1134                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1135                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1136                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1137                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1138                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1139                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1140                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1141                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1142                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1143                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1144                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1145                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1146                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1147                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1148                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1149                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1150                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1151                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1152                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1153                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1154                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1155                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1156                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1157                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1158                 // initialize the samplers to refer to the texture units we use
1159                 p->tex_Texture_First = -1;
1160                 p->tex_Texture_Second = -1;
1161                 p->tex_Texture_GammaRamps = -1;
1162                 p->tex_Texture_Normal = -1;
1163                 p->tex_Texture_Color = -1;
1164                 p->tex_Texture_Gloss = -1;
1165                 p->tex_Texture_Glow = -1;
1166                 p->tex_Texture_SecondaryNormal = -1;
1167                 p->tex_Texture_SecondaryColor = -1;
1168                 p->tex_Texture_SecondaryGloss = -1;
1169                 p->tex_Texture_SecondaryGlow = -1;
1170                 p->tex_Texture_Pants = -1;
1171                 p->tex_Texture_Shirt = -1;
1172                 p->tex_Texture_FogHeightTexture = -1;
1173                 p->tex_Texture_FogMask = -1;
1174                 p->tex_Texture_Lightmap = -1;
1175                 p->tex_Texture_Deluxemap = -1;
1176                 p->tex_Texture_Attenuation = -1;
1177                 p->tex_Texture_Cube = -1;
1178                 p->tex_Texture_Refraction = -1;
1179                 p->tex_Texture_Reflection = -1;
1180                 p->tex_Texture_ShadowMap2D = -1;
1181                 p->tex_Texture_CubeProjection = -1;
1182                 p->tex_Texture_ScreenDepth = -1;
1183                 p->tex_Texture_ScreenNormalMap = -1;
1184                 p->tex_Texture_ScreenDiffuse = -1;
1185                 p->tex_Texture_ScreenSpecular = -1;
1186                 p->tex_Texture_ReflectMask = -1;
1187                 p->tex_Texture_ReflectCube = -1;
1188                 p->tex_Texture_BounceGrid = -1;
1189                 sampler = 0;
1190                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1191                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1192                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1193                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1194                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1195                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1196                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1199                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1200                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1201                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1202                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1203                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1204                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1205                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1206                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1207                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1208                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1209                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1210                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1211                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1212                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1214                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1215                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1216                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1217                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1218                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1219                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1220                 CHECKGLERROR
1221                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1222         }
1223         else
1224                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1225
1226         // free the strings
1227         if (vertexstring)
1228                 Mem_Free(vertexstring);
1229         if (geometrystring)
1230                 Mem_Free(geometrystring);
1231         if (fragmentstring)
1232                 Mem_Free(fragmentstring);
1233 }
1234
1235 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1236 {
1237         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1238         if (r_glsl_permutation != perm)
1239         {
1240                 r_glsl_permutation = perm;
1241                 if (!r_glsl_permutation->program)
1242                 {
1243                         if (!r_glsl_permutation->compiled)
1244                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1245                         if (!r_glsl_permutation->program)
1246                         {
1247                                 // remove features until we find a valid permutation
1248                                 int i;
1249                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1250                                 {
1251                                         // reduce i more quickly whenever it would not remove any bits
1252                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1253                                         if (!(permutation & j))
1254                                                 continue;
1255                                         permutation -= j;
1256                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1257                                         if (!r_glsl_permutation->compiled)
1258                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                                         if (r_glsl_permutation->program)
1260                                                 break;
1261                                 }
1262                                 if (i >= SHADERPERMUTATION_COUNT)
1263                                 {
1264                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1265                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1266                                         qglUseProgram(0);CHECKGLERROR
1267                                         return; // no bit left to clear, entire mode is broken
1268                                 }
1269                         }
1270                 }
1271                 CHECKGLERROR
1272                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1273         }
1274         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1275         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1276         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1277 }
1278
1279 #ifdef SUPPORTD3D
1280
1281 #ifdef SUPPORTD3D
1282 #include <d3d9.h>
1283 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1284 extern D3DCAPS9 vid_d3d9caps;
1285 #endif
1286
1287 struct r_hlsl_permutation_s;
1288 typedef struct r_hlsl_permutation_s
1289 {
1290         /// hash lookup data
1291         struct r_hlsl_permutation_s *hashnext;
1292         unsigned int mode;
1293         unsigned int permutation;
1294
1295         /// indicates if we have tried compiling this permutation already
1296         qboolean compiled;
1297         /// NULL if compilation failed
1298         IDirect3DVertexShader9 *vertexshader;
1299         IDirect3DPixelShader9 *pixelshader;
1300 }
1301 r_hlsl_permutation_t;
1302
1303 typedef enum D3DVSREGISTER_e
1304 {
1305         D3DVSREGISTER_TexMatrix = 0, // float4x4
1306         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1307         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1308         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1309         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1310         D3DVSREGISTER_ModelToLight = 20, // float4x4
1311         D3DVSREGISTER_EyePosition = 24,
1312         D3DVSREGISTER_FogPlane = 25,
1313         D3DVSREGISTER_LightDir = 26,
1314         D3DVSREGISTER_LightPosition = 27,
1315 }
1316 D3DVSREGISTER_t;
1317
1318 typedef enum D3DPSREGISTER_e
1319 {
1320         D3DPSREGISTER_Alpha = 0,
1321         D3DPSREGISTER_BloomBlur_Parameters = 1,
1322         D3DPSREGISTER_ClientTime = 2,
1323         D3DPSREGISTER_Color_Ambient = 3,
1324         D3DPSREGISTER_Color_Diffuse = 4,
1325         D3DPSREGISTER_Color_Specular = 5,
1326         D3DPSREGISTER_Color_Glow = 6,
1327         D3DPSREGISTER_Color_Pants = 7,
1328         D3DPSREGISTER_Color_Shirt = 8,
1329         D3DPSREGISTER_DeferredColor_Ambient = 9,
1330         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1331         D3DPSREGISTER_DeferredColor_Specular = 11,
1332         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1333         D3DPSREGISTER_DeferredMod_Specular = 13,
1334         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1335         D3DPSREGISTER_EyePosition = 15, // unused
1336         D3DPSREGISTER_FogColor = 16,
1337         D3DPSREGISTER_FogHeightFade = 17,
1338         D3DPSREGISTER_FogPlane = 18,
1339         D3DPSREGISTER_FogPlaneViewDist = 19,
1340         D3DPSREGISTER_FogRangeRecip = 20,
1341         D3DPSREGISTER_LightColor = 21,
1342         D3DPSREGISTER_LightDir = 22, // unused
1343         D3DPSREGISTER_LightPosition = 23,
1344         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1345         D3DPSREGISTER_PixelSize = 25,
1346         D3DPSREGISTER_ReflectColor = 26,
1347         D3DPSREGISTER_ReflectFactor = 27,
1348         D3DPSREGISTER_ReflectOffset = 28,
1349         D3DPSREGISTER_RefractColor = 29,
1350         D3DPSREGISTER_Saturation = 30,
1351         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1352         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1353         D3DPSREGISTER_ScreenToDepth = 33,
1354         D3DPSREGISTER_ShadowMap_Parameters = 34,
1355         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1356         D3DPSREGISTER_SpecularPower = 36,
1357         D3DPSREGISTER_UserVec1 = 37,
1358         D3DPSREGISTER_UserVec2 = 38,
1359         D3DPSREGISTER_UserVec3 = 39,
1360         D3DPSREGISTER_UserVec4 = 40,
1361         D3DPSREGISTER_ViewTintColor = 41,
1362         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1363         D3DPSREGISTER_BloomColorSubtract = 43,
1364         D3DPSREGISTER_ViewToLight = 44, // float4x4
1365         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1366         D3DPSREGISTER_NormalmapScrollBlend = 52,
1367         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1368         D3DPSREGISTER_OffsetMapping_Bias = 54,
1369         // next at 54
1370 }
1371 D3DPSREGISTER_t;
1372
1373 /// information about each possible shader permutation
1374 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1375 /// currently selected permutation
1376 r_hlsl_permutation_t *r_hlsl_permutation;
1377 /// storage for permutations linked in the hash table
1378 memexpandablearray_t r_hlsl_permutationarray;
1379
1380 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1381 {
1382         //unsigned int hashdepth = 0;
1383         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1384         r_hlsl_permutation_t *p;
1385         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1386         {
1387                 if (p->mode == mode && p->permutation == permutation)
1388                 {
1389                         //if (hashdepth > 10)
1390                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1391                         return p;
1392                 }
1393                 //hashdepth++;
1394         }
1395         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1396         p->mode = mode;
1397         p->permutation = permutation;
1398         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1399         r_hlsl_permutationhash[mode][hashindex] = p;
1400         //if (hashdepth > 10)
1401         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1402         return p;
1403 }
1404
1405 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1406 {
1407         char *shaderstring;
1408         if (!filename || !filename[0])
1409                 return NULL;
1410         if (!strcmp(filename, "hlsl/default.hlsl"))
1411         {
1412                 if (!hlslshaderstring)
1413                 {
1414                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1415                         if (hlslshaderstring)
1416                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1417                         else
1418                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1419                 }
1420                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1421                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1422                 return shaderstring;
1423         }
1424         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1425         if (shaderstring)
1426         {
1427                 if (printfromdisknotice)
1428                         Con_DPrintf("from disk %s... ", filename);
1429                 return shaderstring;
1430         }
1431         return shaderstring;
1432 }
1433
1434 #include <d3dx9.h>
1435 //#include <d3dx9shader.h>
1436 //#include <d3dx9mesh.h>
1437
1438 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1439 {
1440         DWORD *vsbin = NULL;
1441         DWORD *psbin = NULL;
1442         fs_offset_t vsbinsize;
1443         fs_offset_t psbinsize;
1444 //      IDirect3DVertexShader9 *vs = NULL;
1445 //      IDirect3DPixelShader9 *ps = NULL;
1446         ID3DXBuffer *vslog = NULL;
1447         ID3DXBuffer *vsbuffer = NULL;
1448         ID3DXConstantTable *vsconstanttable = NULL;
1449         ID3DXBuffer *pslog = NULL;
1450         ID3DXBuffer *psbuffer = NULL;
1451         ID3DXConstantTable *psconstanttable = NULL;
1452         int vsresult = 0;
1453         int psresult = 0;
1454         char temp[MAX_INPUTLINE];
1455         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1456         qboolean debugshader = gl_paranoid.integer != 0;
1457         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1458         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1459         if (!debugshader)
1460         {
1461                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1462                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1463         }
1464         if ((!vsbin && vertstring) || (!psbin && fragstring))
1465         {
1466                 const char* dllnames_d3dx9 [] =
1467                 {
1468                         "d3dx9_43.dll",
1469                         "d3dx9_42.dll",
1470                         "d3dx9_41.dll",
1471                         "d3dx9_40.dll",
1472                         "d3dx9_39.dll",
1473                         "d3dx9_38.dll",
1474                         "d3dx9_37.dll",
1475                         "d3dx9_36.dll",
1476                         "d3dx9_35.dll",
1477                         "d3dx9_34.dll",
1478                         "d3dx9_33.dll",
1479                         "d3dx9_32.dll",
1480                         "d3dx9_31.dll",
1481                         "d3dx9_30.dll",
1482                         "d3dx9_29.dll",
1483                         "d3dx9_28.dll",
1484                         "d3dx9_27.dll",
1485                         "d3dx9_26.dll",
1486                         "d3dx9_25.dll",
1487                         "d3dx9_24.dll",
1488                         NULL
1489                 };
1490                 dllhandle_t d3dx9_dll = NULL;
1491                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1493                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1494                 dllfunction_t d3dx9_dllfuncs[] =
1495                 {
1496                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1497                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1498                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1499                         {NULL, NULL}
1500                 };
1501                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1502                 {
1503                         DWORD shaderflags = 0;
1504                         if (debugshader)
1505                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1506                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1507                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1508                         if (vertstring && vertstring[0])
1509                         {
1510                                 if (debugshader)
1511                                 {
1512 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1513 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1514                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1515                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1516                                 }
1517                                 else
1518                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 if (vsbuffer)
1520                                 {
1521                                         vsbinsize = vsbuffer->GetBufferSize();
1522                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1523                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1524                                         vsbuffer->Release();
1525                                 }
1526                                 if (vslog)
1527                                 {
1528                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1529                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1530                                         vslog->Release();
1531                                 }
1532                         }
1533                         if (fragstring && fragstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1538 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1539                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1540                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1541                                 }
1542                                 else
1543                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 if (psbuffer)
1545                                 {
1546                                         psbinsize = psbuffer->GetBufferSize();
1547                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1548                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1549                                         psbuffer->Release();
1550                                 }
1551                                 if (pslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         pslog->Release();
1556                                 }
1557                         }
1558                         Sys_UnloadLibrary(&d3dx9_dll);
1559                 }
1560                 else
1561                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1562         }
1563         if (vsbin && psbin)
1564         {
1565                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1566                 if (FAILED(vsresult))
1567                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1568                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1569                 if (FAILED(psresult))
1570                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1571         }
1572         // free the shader data
1573         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1574         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1575 }
1576
1577 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1578 {
1579         int i;
1580         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1581         int vertstring_length = 0;
1582         int geomstring_length = 0;
1583         int fragstring_length = 0;
1584         char *t;
1585         char *vertexstring, *geometrystring, *fragmentstring;
1586         char *vertstring, *geomstring, *fragstring;
1587         char permutationname[256];
1588         char cachename[256];
1589         int vertstrings_count = 0;
1590         int geomstrings_count = 0;
1591         int fragstrings_count = 0;
1592         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1593         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1594         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1595
1596         if (p->compiled)
1597                 return;
1598         p->compiled = true;
1599         p->vertexshader = NULL;
1600         p->pixelshader = NULL;
1601
1602         permutationname[0] = 0;
1603         cachename[0] = 0;
1604         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1605         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1606         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1607
1608         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1609         strlcat(cachename, "hlsl/", sizeof(cachename));
1610
1611         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1612         vertstrings_count = 0;
1613         geomstrings_count = 0;
1614         fragstrings_count = 0;
1615         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1616         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1617         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1618
1619         // the first pretext is which type of shader to compile as
1620         // (later these will all be bound together as a program object)
1621         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1622         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1623         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1624
1625         // the second pretext is the mode (for example a light source)
1626         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1627         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1628         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1629         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1630         strlcat(cachename, modeinfo->name, sizeof(cachename));
1631
1632         // now add all the permutation pretexts
1633         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1634         {
1635                 if (permutation & (1<<i))
1636                 {
1637                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1639                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1640                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1641                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1642                 }
1643                 else
1644                 {
1645                         // keep line numbers correct
1646                         vertstrings_list[vertstrings_count++] = "\n";
1647                         geomstrings_list[geomstrings_count++] = "\n";
1648                         fragstrings_list[fragstrings_count++] = "\n";
1649                 }
1650         }
1651
1652         // add static parms
1653         R_CompileShader_AddStaticParms(mode, permutation);
1654         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         vertstrings_count += shaderstaticparms_count;
1656         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         geomstrings_count += shaderstaticparms_count;
1658         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         fragstrings_count += shaderstaticparms_count;
1660
1661         // replace spaces in the cachename with _ characters
1662         for (i = 0;cachename[i];i++)
1663                 if (cachename[i] == ' ')
1664                         cachename[i] = '_';
1665
1666         // now append the shader text itself
1667         vertstrings_list[vertstrings_count++] = vertexstring;
1668         geomstrings_list[geomstrings_count++] = geometrystring;
1669         fragstrings_list[fragstrings_count++] = fragmentstring;
1670
1671         // if any sources were NULL, clear the respective list
1672         if (!vertexstring)
1673                 vertstrings_count = 0;
1674         if (!geometrystring)
1675                 geomstrings_count = 0;
1676         if (!fragmentstring)
1677                 fragstrings_count = 0;
1678
1679         vertstring_length = 0;
1680         for (i = 0;i < vertstrings_count;i++)
1681                 vertstring_length += strlen(vertstrings_list[i]);
1682         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1683         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1684                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1685
1686         geomstring_length = 0;
1687         for (i = 0;i < geomstrings_count;i++)
1688                 geomstring_length += strlen(geomstrings_list[i]);
1689         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1690         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1691                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1692
1693         fragstring_length = 0;
1694         for (i = 0;i < fragstrings_count;i++)
1695                 fragstring_length += strlen(fragstrings_list[i]);
1696         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1697         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1698                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1699
1700         // try to load the cached shader, or generate one
1701         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1702
1703         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1704                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1705         else
1706                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1707
1708         // free the strings
1709         if (vertstring)
1710                 Mem_Free(vertstring);
1711         if (geomstring)
1712                 Mem_Free(geomstring);
1713         if (fragstring)
1714                 Mem_Free(fragstring);
1715         if (vertexstring)
1716                 Mem_Free(vertexstring);
1717         if (geometrystring)
1718                 Mem_Free(geometrystring);
1719         if (fragmentstring)
1720                 Mem_Free(fragmentstring);
1721 }
1722
1723 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1724 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1725 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1726 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1727 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1728 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729
1730 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1731 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1732 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1733 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736
1737 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1738 {
1739         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1740         if (r_hlsl_permutation != perm)
1741         {
1742                 r_hlsl_permutation = perm;
1743                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1744                 {
1745                         if (!r_hlsl_permutation->compiled)
1746                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1747                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                         {
1749                                 // remove features until we find a valid permutation
1750                                 int i;
1751                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1752                                 {
1753                                         // reduce i more quickly whenever it would not remove any bits
1754                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1755                                         if (!(permutation & j))
1756                                                 continue;
1757                                         permutation -= j;
1758                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1759                                         if (!r_hlsl_permutation->compiled)
1760                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1762                                                 break;
1763                                 }
1764                                 if (i >= SHADERPERMUTATION_COUNT)
1765                                 {
1766                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1767                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1768                                         return; // no bit left to clear, entire mode is broken
1769                                 }
1770                         }
1771                 }
1772                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1773                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1774         }
1775         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1776         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1777         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1778 }
1779 #endif
1780
1781 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1782 {
1783         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1784         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1785         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1786         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1787 }
1788
1789 void R_GLSL_Restart_f(void)
1790 {
1791         unsigned int i, limit;
1792         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1793                 Mem_Free(glslshaderstring);
1794         glslshaderstring = NULL;
1795         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1796                 Mem_Free(hlslshaderstring);
1797         hlslshaderstring = NULL;
1798         switch(vid.renderpath)
1799         {
1800         case RENDERPATH_D3D9:
1801 #ifdef SUPPORTD3D
1802                 {
1803                         r_hlsl_permutation_t *p;
1804                         r_hlsl_permutation = NULL;
1805                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1806                         for (i = 0;i < limit;i++)
1807                         {
1808                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1809                                 {
1810                                         if (p->vertexshader)
1811                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1812                                         if (p->pixelshader)
1813                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1814                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1815                                 }
1816                         }
1817                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1818                 }
1819 #endif
1820                 break;
1821         case RENDERPATH_D3D10:
1822                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1823                 break;
1824         case RENDERPATH_D3D11:
1825                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_GL20:
1828         case RENDERPATH_GLES2:
1829                 {
1830                         r_glsl_permutation_t *p;
1831                         r_glsl_permutation = NULL;
1832                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1833                         for (i = 0;i < limit;i++)
1834                         {
1835                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1836                                 {
1837                                         GL_Backend_FreeProgram(p->program);
1838                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1839                                 }
1840                         }
1841                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1842                 }
1843                 break;
1844         case RENDERPATH_GL11:
1845         case RENDERPATH_GL13:
1846         case RENDERPATH_GLES1:
1847                 break;
1848         case RENDERPATH_SOFT:
1849                 break;
1850         }
1851 }
1852
1853 void R_GLSL_DumpShader_f(void)
1854 {
1855         int i;
1856         qfile_t *file;
1857
1858         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1859         if (file)
1860         {
1861                 FS_Print(file, "/* The engine may define the following macros:\n");
1862                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1863                 for (i = 0;i < SHADERMODE_COUNT;i++)
1864                         FS_Print(file, glslshadermodeinfo[i].pretext);
1865                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1866                         FS_Print(file, shaderpermutationinfo[i].pretext);
1867                 FS_Print(file, "*/\n");
1868                 FS_Print(file, builtinshaderstring);
1869                 FS_Close(file);
1870                 Con_Printf("glsl/default.glsl written\n");
1871         }
1872         else
1873                 Con_Printf("failed to write to glsl/default.glsl\n");
1874
1875         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1876         if (file)
1877         {
1878                 FS_Print(file, "/* The engine may define the following macros:\n");
1879                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1880                 for (i = 0;i < SHADERMODE_COUNT;i++)
1881                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1882                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1883                         FS_Print(file, shaderpermutationinfo[i].pretext);
1884                 FS_Print(file, "*/\n");
1885                 FS_Print(file, builtinhlslshaderstring);
1886                 FS_Close(file);
1887                 Con_Printf("hlsl/default.hlsl written\n");
1888         }
1889         else
1890                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1891 }
1892
1893 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1894 {
1895         unsigned int permutation = 0;
1896         if (r_trippy.integer && !notrippy)
1897                 permutation |= SHADERPERMUTATION_TRIPPY;
1898         permutation |= SHADERPERMUTATION_VIEWTINT;
1899         if (first)
1900                 permutation |= SHADERPERMUTATION_DIFFUSE;
1901         if (second)
1902                 permutation |= SHADERPERMUTATION_SPECULAR;
1903         if (texturemode == GL_MODULATE)
1904                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1905         else if (texturemode == GL_ADD)
1906                 permutation |= SHADERPERMUTATION_GLOW;
1907         else if (texturemode == GL_DECAL)
1908                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1909         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1910                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1911         if (suppresstexalpha)
1912                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1913         if (!second)
1914                 texturemode = GL_MODULATE;
1915         if (vid.allowalphatocoverage)
1916                 GL_AlphaToCoverage(false);
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1922                 R_Mesh_TexBind(GL20TU_FIRST , first );
1923                 R_Mesh_TexBind(GL20TU_SECOND, second);
1924                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1925                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1926 #endif
1927                 break;
1928         case RENDERPATH_D3D10:
1929                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_D3D11:
1932                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1933                 break;
1934         case RENDERPATH_GL20:
1935         case RENDERPATH_GLES2:
1936                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1938                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1939                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941                 break;
1942         case RENDERPATH_GL13:
1943         case RENDERPATH_GLES1:
1944                 R_Mesh_TexBind(0, first );
1945                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946                 R_Mesh_TexBind(1, second);
1947                 if (second)
1948                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, first );
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955                 R_Mesh_TexBind(GL20TU_FIRST , first );
1956                 R_Mesh_TexBind(GL20TU_SECOND, second);
1957                 break;
1958         }
1959 }
1960
1961 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1962 {
1963         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1964 }
1965
1966 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1967 {
1968         unsigned int permutation = 0;
1969         if (r_trippy.integer && !notrippy)
1970                 permutation |= SHADERPERMUTATION_TRIPPY;
1971         if (vid.allowalphatocoverage)
1972                 GL_AlphaToCoverage(false);
1973         switch (vid.renderpath)
1974         {
1975         case RENDERPATH_D3D9:
1976 #ifdef SUPPORTD3D
1977                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1978 #endif
1979                 break;
1980         case RENDERPATH_D3D10:
1981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982                 break;
1983         case RENDERPATH_D3D11:
1984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1985                 break;
1986         case RENDERPATH_GL20:
1987         case RENDERPATH_GLES2:
1988                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1989                 break;
1990         case RENDERPATH_GL13:
1991         case RENDERPATH_GLES1:
1992                 R_Mesh_TexBind(0, 0);
1993                 R_Mesh_TexBind(1, 0);
1994                 break;
1995         case RENDERPATH_GL11:
1996                 R_Mesh_TexBind(0, 0);
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2000                 break;
2001         }
2002 }
2003
2004 void R_SetupShader_ShowDepth(qboolean notrippy)
2005 {
2006         int permutation = 0;
2007         if (r_trippy.integer && !notrippy)
2008                 permutation |= SHADERPERMUTATION_TRIPPY;
2009         if (vid.allowalphatocoverage)
2010                 GL_AlphaToCoverage(false);
2011         switch (vid.renderpath)
2012         {
2013         case RENDERPATH_D3D9:
2014 #ifdef SUPPORTHLSL
2015                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2016 #endif
2017                 break;
2018         case RENDERPATH_D3D10:
2019                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2020                 break;
2021         case RENDERPATH_D3D11:
2022                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2023                 break;
2024         case RENDERPATH_GL20:
2025         case RENDERPATH_GLES2:
2026                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         case RENDERPATH_GL13:
2029         case RENDERPATH_GLES1:
2030                 break;
2031         case RENDERPATH_GL11:
2032                 break;
2033         case RENDERPATH_SOFT:
2034                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2035                 break;
2036         }
2037 }
2038
2039 extern qboolean r_shadow_usingdeferredprepass;
2040 extern cvar_t r_shadow_deferred_8bitrange;
2041 extern rtexture_t *r_shadow_attenuationgradienttexture;
2042 extern rtexture_t *r_shadow_attenuation2dtexture;
2043 extern rtexture_t *r_shadow_attenuation3dtexture;
2044 extern qboolean r_shadow_usingshadowmap2d;
2045 extern qboolean r_shadow_usingshadowmaportho;
2046 extern float r_shadow_shadowmap_texturescale[2];
2047 extern float r_shadow_shadowmap_parameters[4];
2048 extern qboolean r_shadow_shadowmapvsdct;
2049 extern qboolean r_shadow_shadowmapsampler;
2050 extern int r_shadow_shadowmappcf;
2051 extern rtexture_t *r_shadow_shadowmap2dtexture;
2052 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2053 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2054 extern matrix4x4_t r_shadow_shadowmapmatrix;
2055 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2056 extern int r_shadow_prepass_width;
2057 extern int r_shadow_prepass_height;
2058 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2059 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2060 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2061 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2062 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2063
2064 #define BLENDFUNC_ALLOWS_COLORMOD      1
2065 #define BLENDFUNC_ALLOWS_FOG           2
2066 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2067 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2068 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2069 static int R_BlendFuncFlags(int src, int dst)
2070 {
2071         int r = 0;
2072
2073         // a blendfunc allows colormod if:
2074         // a) it can never keep the destination pixel invariant, or
2075         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2076         // this is to prevent unintended side effects from colormod
2077
2078         // a blendfunc allows fog if:
2079         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2080         // this is to prevent unintended side effects from fog
2081
2082         // these checks are the output of fogeval.pl
2083
2084         r |= BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2094         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2097         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2103         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2104         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2106
2107         return r;
2108 }
2109
2110 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)
2111 {
2112         // select a permutation of the lighting shader appropriate to this
2113         // combination of texture, entity, light source, and fogging, only use the
2114         // minimum features necessary to avoid wasting rendering time in the
2115         // fragment shader on features that are not being used
2116         unsigned int permutation = 0;
2117         unsigned int mode = 0;
2118         int blendfuncflags;
2119         static float dummy_colormod[3] = {1, 1, 1};
2120         float *colormod = rsurface.colormod;
2121         float m16f[16];
2122         matrix4x4_t tempmatrix;
2123         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2124         if (r_trippy.integer && !notrippy)
2125                 permutation |= SHADERPERMUTATION_TRIPPY;
2126         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2127                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2128         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2129                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2130         if (rsurfacepass == RSURFPASS_BACKGROUND)
2131         {
2132                 // distorted background
2133                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2134                 {
2135                         mode = SHADERMODE_WATER;
2136                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2137                         {
2138                                 // this is the right thing to do for wateralpha
2139                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2140                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2141                         }
2142                         else
2143                         {
2144                                 // this is the right thing to do for entity alpha
2145                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                         }
2148                 }
2149                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2150                 {
2151                         mode = SHADERMODE_REFRACTION;
2152                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                 }
2155                 else
2156                 {
2157                         mode = SHADERMODE_GENERIC;
2158                         permutation |= SHADERPERMUTATION_DIFFUSE;
2159                         GL_BlendFunc(GL_ONE, GL_ZERO);
2160                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2161                 }
2162                 if (vid.allowalphatocoverage)
2163                         GL_AlphaToCoverage(false);
2164         }
2165         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2166         {
2167                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2168                 {
2169                         switch(rsurface.texture->offsetmapping)
2170                         {
2171                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2172                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2173                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_OFF: break;
2175                         }
2176                 }
2177                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2178                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2179                 // normalmap (deferred prepass), may use alpha test on diffuse
2180                 mode = SHADERMODE_DEFERREDGEOMETRY;
2181                 GL_BlendFunc(GL_ONE, GL_ZERO);
2182                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2183                 if (vid.allowalphatocoverage)
2184                         GL_AlphaToCoverage(false);
2185         }
2186         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2187         {
2188                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2189                 {
2190                         switch(rsurface.texture->offsetmapping)
2191                         {
2192                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2193                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2194                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_OFF: break;
2196                         }
2197                 }
2198                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2199                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2200                 // light source
2201                 mode = SHADERMODE_LIGHTSOURCE;
2202                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2203                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2204                 if (diffusescale > 0)
2205                         permutation |= SHADERPERMUTATION_DIFFUSE;
2206                 if (specularscale > 0)
2207                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2208                 if (r_refdef.fogenabled)
2209                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2210                 if (rsurface.texture->colormapping)
2211                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2212                 if (r_shadow_usingshadowmap2d)
2213                 {
2214                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2215                         if(r_shadow_shadowmapvsdct)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2217
2218                         if (r_shadow_shadowmapsampler)
2219                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2220                         if (r_shadow_shadowmappcf > 1)
2221                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2222                         else if (r_shadow_shadowmappcf)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2224                 }
2225                 if (rsurface.texture->reflectmasktexture)
2226                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2228                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2229                 if (vid.allowalphatocoverage)
2230                         GL_AlphaToCoverage(false);
2231         }
2232         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2233         {
2234                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2235                 {
2236                         switch(rsurface.texture->offsetmapping)
2237                         {
2238                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2239                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_OFF: break;
2242                         }
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246                 // unshaded geometry (fullbright or ambient model lighting)
2247                 mode = SHADERMODE_FLATCOLOR;
2248                 ambientscale = diffusescale = specularscale = 0;
2249                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250                         permutation |= SHADERPERMUTATION_GLOW;
2251                 if (r_refdef.fogenabled)
2252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253                 if (rsurface.texture->colormapping)
2254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2255                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256                 {
2257                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259
2260                         if (r_shadow_shadowmapsampler)
2261                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262                         if (r_shadow_shadowmappcf > 1)
2263                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264                         else if (r_shadow_shadowmappcf)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266                 }
2267                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2268                         permutation |= SHADERPERMUTATION_REFLECTION;
2269                 if (rsurface.texture->reflectmasktexture)
2270                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2271                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2272                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273                 // when using alphatocoverage, we don't need alphakill
2274                 if (vid.allowalphatocoverage)
2275                 {
2276                         if (r_transparent_alphatocoverage.integer)
2277                         {
2278                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2279                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2280                         }
2281                         else
2282                                 GL_AlphaToCoverage(false);
2283                 }
2284         }
2285         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2286         {
2287                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2288                 {
2289                         switch(rsurface.texture->offsetmapping)
2290                         {
2291                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2292                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2293                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_OFF: break;
2295                         }
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2298                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2299                 // directional model lighting
2300                 mode = SHADERMODE_LIGHTDIRECTION;
2301                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2302                         permutation |= SHADERPERMUTATION_GLOW;
2303                 permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2313                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2314
2315                         if (r_shadow_shadowmapsampler)
2316                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2317                         if (r_shadow_shadowmappcf > 1)
2318                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2319                         else if (r_shadow_shadowmappcf)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2321                 }
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2323                         permutation |= SHADERPERMUTATION_REFLECTION;
2324                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2325                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2326                 if (rsurface.texture->reflectmasktexture)
2327                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2328                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2329                 {
2330                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2331                         if (r_shadow_bouncegriddirectional)
2332                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2333                 }
2334                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2335                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 // when using alphatocoverage, we don't need alphakill
2337                 if (vid.allowalphatocoverage)
2338                 {
2339                         if (r_transparent_alphatocoverage.integer)
2340                         {
2341                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2342                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2343                         }
2344                         else
2345                                 GL_AlphaToCoverage(false);
2346                 }
2347         }
2348         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2349         {
2350                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2351                 {
2352                         switch(rsurface.texture->offsetmapping)
2353                         {
2354                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2355                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2356                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_OFF: break;
2358                         }
2359                 }
2360                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2361                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2362                 // ambient model lighting
2363                 mode = SHADERMODE_LIGHTDIRECTION;
2364                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2365                         permutation |= SHADERPERMUTATION_GLOW;
2366                 if (r_refdef.fogenabled)
2367                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2368                 if (rsurface.texture->colormapping)
2369                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2370                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2371                 {
2372                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2373                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2374
2375                         if (r_shadow_shadowmapsampler)
2376                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2377                         if (r_shadow_shadowmappcf > 1)
2378                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2379                         else if (r_shadow_shadowmappcf)
2380                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2383                         permutation |= SHADERPERMUTATION_REFLECTION;
2384                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2385                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2386                 if (rsurface.texture->reflectmasktexture)
2387                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2388                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2389                 {
2390                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2391                         if (r_shadow_bouncegriddirectional)
2392                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2393                 }
2394                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2395                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 // when using alphatocoverage, we don't need alphakill
2397                 if (vid.allowalphatocoverage)
2398                 {
2399                         if (r_transparent_alphatocoverage.integer)
2400                         {
2401                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2402                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2403                         }
2404                         else
2405                                 GL_AlphaToCoverage(false);
2406                 }
2407         }
2408         else
2409         {
2410                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2411                 {
2412                         switch(rsurface.texture->offsetmapping)
2413                         {
2414                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2415                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2416                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2417                         case OFFSETMAPPING_OFF: break;
2418                         }
2419                 }
2420                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2421                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2422                 // lightmapped wall
2423                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2424                         permutation |= SHADERPERMUTATION_GLOW;
2425                 if (r_refdef.fogenabled)
2426                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2427                 if (rsurface.texture->colormapping)
2428                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2429                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2430                 {
2431                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2432                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2433
2434                         if (r_shadow_shadowmapsampler)
2435                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2436                         if (r_shadow_shadowmappcf > 1)
2437                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2438                         else if (r_shadow_shadowmappcf)
2439                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2440                 }
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2442                         permutation |= SHADERPERMUTATION_REFLECTION;
2443                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2444                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2445                 if (rsurface.texture->reflectmasktexture)
2446                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2447                 if (FAKELIGHT_ENABLED)
2448                 {
2449                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2450                         mode = SHADERMODE_FAKELIGHT;
2451                         permutation |= SHADERPERMUTATION_DIFFUSE;
2452                         if (specularscale > 0)
2453                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2454                 }
2455                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2456                 {
2457                         // deluxemapping (light direction texture)
2458                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2459                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2460                         else
2461                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (r_glsl_deluxemapping.integer >= 2)
2467                 {
2468                         // fake deluxemapping (uniform light direction in tangentspace)
2469                         if (rsurface.uselightmaptexture)
2470                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2471                         else
2472                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2473                         permutation |= SHADERPERMUTATION_DIFFUSE;
2474                         if (specularscale > 0)
2475                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2476                 }
2477                 else if (rsurface.uselightmaptexture)
2478                 {
2479                         // ordinary lightmapping (q1bsp, q3bsp)
2480                         mode = SHADERMODE_LIGHTMAP;
2481                 }
2482                 else
2483                 {
2484                         // ordinary vertex coloring (q3bsp)
2485                         mode = SHADERMODE_VERTEXCOLOR;
2486                 }
2487                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2488                 {
2489                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2490                         if (r_shadow_bouncegriddirectional)
2491                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2492                 }
2493                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2494                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2495                 // when using alphatocoverage, we don't need alphakill
2496                 if (vid.allowalphatocoverage)
2497                 {
2498                         if (r_transparent_alphatocoverage.integer)
2499                         {
2500                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2501                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2502                         }
2503                         else
2504                                 GL_AlphaToCoverage(false);
2505                 }
2506         }
2507         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2508                 colormod = dummy_colormod;
2509         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2510                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2511         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2512                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2513         switch(vid.renderpath)
2514         {
2515         case RENDERPATH_D3D9:
2516 #ifdef SUPPORTD3D
2517                 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);
2518                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2519                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2520                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2521                 if (mode == SHADERMODE_LIGHTSOURCE)
2522                 {
2523                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2524                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2525                 }
2526                 else
2527                 {
2528                         if (mode == SHADERMODE_LIGHTDIRECTION)
2529                         {
2530                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2531                         }
2532                 }
2533                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2534                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2535                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2536                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2537                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2538
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2544                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2545                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2546
2547                         // additive passes are only darkened by fog, not tinted
2548                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2549                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2550                 }
2551                 else
2552                 {
2553                         if (mode == SHADERMODE_FLATCOLOR)
2554                         {
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2556                         }
2557                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2558                         {
2559                                 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]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2561                                 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);
2562                                 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);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2566                         }
2567                         else
2568                         {
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2571                                 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);
2572                                 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);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2574                         }
2575                         // additive passes are only darkened by fog, not tinted
2576                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2578                         else
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2580                         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);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2583                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2584                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2586                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2587                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2588                         if (mode == SHADERMODE_WATER)
2589                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2590                 }
2591                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2592                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2593                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2594                 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));
2595                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2596                 if (rsurface.texture->pantstexture)
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2598                 else
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2600                 if (rsurface.texture->shirttexture)
2601                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2602                 else
2603                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2604                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2606                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2607                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2608                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2609                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2610                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2611                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2612                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2613                         );
2614                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2616                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2617                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2618
2619                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2620                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2621                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2622                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2623                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2624                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2625                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2626                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2627                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2628                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2629                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2630                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2631                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2632                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2633                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2634                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2635                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2636                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2637                 {
2638                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2639                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2640                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642                 else
2643                 {
2644                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2645                 }
2646 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2647 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2648                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2649                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2650                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2651                 {
2652                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2653                         if (rsurface.rtlight)
2654                         {
2655                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2656                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2657                         }
2658                 }
2659 #endif
2660                 break;
2661         case RENDERPATH_D3D10:
2662                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2663                 break;
2664         case RENDERPATH_D3D11:
2665                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2666                 break;
2667         case RENDERPATH_GL20:
2668         case RENDERPATH_GLES2:
2669                 if (!vid.useinterleavedarrays)
2670                 {
2671                         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);
2672                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2673                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2675                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2676                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2677                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2678                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2679                 }
2680                 else
2681                 {
2682                         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);
2683                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2684                 }
2685                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2686                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2687                 if (mode == SHADERMODE_LIGHTSOURCE)
2688                 {
2689                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2690                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2691                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2692                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2693                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2694                         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);
2695         
2696                         // additive passes are only darkened by fog, not tinted
2697                         if (r_glsl_permutation->loc_FogColor >= 0)
2698                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2699                         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);
2700                 }
2701                 else
2702                 {
2703                         if (mode == SHADERMODE_FLATCOLOR)
2704                         {
2705                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2706                         }
2707                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2708                         {
2709                                 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]);
2710                                 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]);
2711                                 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);
2712                                 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);
2713                                 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);
2714                                 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]);
2715                                 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]);
2716                         }
2717                         else
2718                         {
2719                                 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]);
2720                                 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]);
2721                                 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);
2722                                 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);
2723                                 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);
2724                         }
2725                         // additive passes are only darkened by fog, not tinted
2726                         if (r_glsl_permutation->loc_FogColor >= 0)
2727                         {
2728                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2729                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2730                                 else
2731                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2732                         }
2733                         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);
2734                         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]);
2735                         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]);
2736                         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]);
2737                         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]);
2738                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2739                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2740                         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);
2741                         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]);
2742                 }
2743                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2744                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2745                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2746                 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]);
2747                 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]);
2748
2749                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2750                 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));
2751                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2752                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2753                 {
2754                         if (rsurface.texture->pantstexture)
2755                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2756                         else
2757                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2758                 }
2759                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2760                 {
2761                         if (rsurface.texture->shirttexture)
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2763                         else
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2765                 }
2766                 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]);
2767                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2768                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2769                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2770                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2771                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2772                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2773                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2774                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2775                         );
2776                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2777                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2778                 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]);
2779                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2780                 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);}
2781                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2782
2783                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2784                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2785                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2786                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2787                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2788                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2789                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2790                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2791                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2792                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2794                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2795                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2796                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2797                 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);
2798                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2799                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2800                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2801                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2802                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2803                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2804                 {
2805                         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);
2806                         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);
2807                         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);
2808                 }
2809                 else
2810                 {
2811                         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);
2812                 }
2813                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2814                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2815                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2816                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2817                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2818                 {
2819                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2820                         if (rsurface.rtlight)
2821                         {
2822                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2823                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2824                         }
2825                 }
2826                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2827                 CHECKGLERROR
2828                 break;
2829         case RENDERPATH_GL11:
2830         case RENDERPATH_GL13:
2831         case RENDERPATH_GLES1:
2832                 break;
2833         case RENDERPATH_SOFT:
2834                 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);
2835                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2836                 R_SetupShader_SetPermutationSoft(mode, permutation);
2837                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2838                 if (mode == SHADERMODE_LIGHTSOURCE)
2839                 {
2840                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2841                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2843                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2846         
2847                         // additive passes are only darkened by fog, not tinted
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2849                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2850                 }
2851                 else
2852                 {
2853                         if (mode == SHADERMODE_FLATCOLOR)
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2856                         }
2857                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2858                         {
2859                                 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]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2861                                 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);
2862                                 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);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2864                                 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]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2866                         }
2867                         else
2868                         {
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2871                                 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);
2872                                 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);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2874                         }
2875                         // additive passes are only darkened by fog, not tinted
2876                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2878                         else
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2880                         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);
2881                         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]);
2882                         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]);
2883                         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]);
2884                         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]);
2885                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2886                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2887                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2888                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2889                 }
2890                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2891                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2892                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2893                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2894                 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]);
2895
2896                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2897                 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));
2898                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2899                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2900                 {
2901                         if (rsurface.texture->pantstexture)
2902                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2903                         else
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2905                 }
2906                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2907                 {
2908                         if (rsurface.texture->shirttexture)
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2910                         else
2911                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2912                 }
2913                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2914                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2915                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2916                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2917                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2918                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2919                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2920                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2921                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2922                         );
2923                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2924                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2925                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2927
2928                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2929                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2930                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2931                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2932                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2936                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2938                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2940                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2941                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2942                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2943                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2944                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2945                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2946                 {
2947                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2948                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2949                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2950                 }
2951                 else
2952                 {
2953                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2954                 }
2955 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2957                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2959                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2960                 {
2961                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2962                         if (rsurface.rtlight)
2963                         {
2964                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2965                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2966                         }
2967                 }
2968                 break;
2969         }
2970 }
2971
2972 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2973 {
2974         // select a permutation of the lighting shader appropriate to this
2975         // combination of texture, entity, light source, and fogging, only use the
2976         // minimum features necessary to avoid wasting rendering time in the
2977         // fragment shader on features that are not being used
2978         unsigned int permutation = 0;
2979         unsigned int mode = 0;
2980         const float *lightcolorbase = rtlight->currentcolor;
2981         float ambientscale = rtlight->ambientscale;
2982         float diffusescale = rtlight->diffusescale;
2983         float specularscale = rtlight->specularscale;
2984         // this is the location of the light in view space
2985         vec3_t viewlightorigin;
2986         // this transforms from view space (camera) to light space (cubemap)
2987         matrix4x4_t viewtolight;
2988         matrix4x4_t lighttoview;
2989         float viewtolight16f[16];
2990         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2991         // light source
2992         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2993         if (rtlight->currentcubemap != r_texture_whitecube)
2994                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2995         if (diffusescale > 0)
2996                 permutation |= SHADERPERMUTATION_DIFFUSE;
2997         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2998                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2999         if (r_shadow_usingshadowmap2d)
3000         {
3001                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3002                 if (r_shadow_shadowmapvsdct)
3003                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3004
3005                 if (r_shadow_shadowmapsampler)
3006                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3007                 if (r_shadow_shadowmappcf > 1)
3008                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3009                 else if (r_shadow_shadowmappcf)
3010                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3011         }
3012         if (vid.allowalphatocoverage)
3013                 GL_AlphaToCoverage(false);
3014         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3015         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3016         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3017         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3018         switch(vid.renderpath)
3019         {
3020         case RENDERPATH_D3D9:
3021 #ifdef SUPPORTD3D
3022                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3023                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3024                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3028                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3029                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3030                 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);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3033
3034                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3035                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3036                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3037                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3038                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3039                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3040 #endif
3041                 break;
3042         case RENDERPATH_D3D10:
3043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3044                 break;
3045         case RENDERPATH_D3D11:
3046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3047                 break;
3048         case RENDERPATH_GL20:
3049         case RENDERPATH_GLES2:
3050                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3051                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3052                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3053                 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);
3054                 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);
3055                 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);
3056                 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]);
3057                 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]);
3058                 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);
3059                 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]);
3060                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3061
3062                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3063                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3064                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3065                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3066                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3067                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3068                 break;
3069         case RENDERPATH_GL11:
3070         case RENDERPATH_GL13:
3071         case RENDERPATH_GLES1:
3072                 break;
3073         case RENDERPATH_SOFT:
3074                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3076                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3077                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3081                 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]);
3082                 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);
3083                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3084                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3085
3086                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3087                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3088                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3089                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3090                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3091                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3092                 break;
3093         }
3094 }
3095
3096 #define SKINFRAME_HASH 1024
3097
3098 typedef struct
3099 {
3100         int loadsequence; // incremented each level change
3101         memexpandablearray_t array;
3102         skinframe_t *hash[SKINFRAME_HASH];
3103 }
3104 r_skinframe_t;
3105 r_skinframe_t r_skinframe;
3106
3107 void R_SkinFrame_PrepareForPurge(void)
3108 {
3109         r_skinframe.loadsequence++;
3110         // wrap it without hitting zero
3111         if (r_skinframe.loadsequence >= 200)
3112                 r_skinframe.loadsequence = 1;
3113 }
3114
3115 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3116 {
3117         if (!skinframe)
3118                 return;
3119         // mark the skinframe as used for the purging code
3120         skinframe->loadsequence = r_skinframe.loadsequence;
3121 }
3122
3123 void R_SkinFrame_Purge(void)
3124 {
3125         int i;
3126         skinframe_t *s;
3127         for (i = 0;i < SKINFRAME_HASH;i++)
3128         {
3129                 for (s = r_skinframe.hash[i];s;s = s->next)
3130                 {
3131                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3132                         {
3133                                 if (s->merged == s->base)
3134                                         s->merged = NULL;
3135                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3136                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3137                                 R_PurgeTexture(s->merged);s->merged = NULL;
3138                                 R_PurgeTexture(s->base  );s->base   = NULL;
3139                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3140                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3141                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3142                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3143                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3144                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3145                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3146                                 s->loadsequence = 0;
3147                         }
3148                 }
3149         }
3150 }
3151
3152 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3153         skinframe_t *item;
3154         char basename[MAX_QPATH];
3155
3156         Image_StripImageExtension(name, basename, sizeof(basename));
3157
3158         if( last == NULL ) {
3159                 int hashindex;
3160                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3161                 item = r_skinframe.hash[hashindex];
3162         } else {
3163                 item = last->next;
3164         }
3165
3166         // linearly search through the hash bucket
3167         for( ; item ; item = item->next ) {
3168                 if( !strcmp( item->basename, basename ) ) {
3169                         return item;
3170                 }
3171         }
3172         return NULL;
3173 }
3174
3175 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3176 {
3177         skinframe_t *item;
3178         int hashindex;
3179         char basename[MAX_QPATH];
3180
3181         Image_StripImageExtension(name, basename, sizeof(basename));
3182
3183         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3184         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3185                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3186                         break;
3187
3188         if (!item) {
3189                 rtexture_t *dyntexture;
3190                 // check whether its a dynamic texture
3191                 dyntexture = CL_GetDynTexture( basename );
3192                 if (!add && !dyntexture)
3193                         return NULL;
3194                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3195                 memset(item, 0, sizeof(*item));
3196                 strlcpy(item->basename, basename, sizeof(item->basename));
3197                 item->base = dyntexture; // either NULL or dyntexture handle
3198                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3199                 item->comparewidth = comparewidth;
3200                 item->compareheight = compareheight;
3201                 item->comparecrc = comparecrc;
3202                 item->next = r_skinframe.hash[hashindex];
3203                 r_skinframe.hash[hashindex] = item;
3204         }
3205         else if (textureflags & TEXF_FORCE_RELOAD)
3206         {
3207                 rtexture_t *dyntexture;
3208                 // check whether its a dynamic texture
3209                 dyntexture = CL_GetDynTexture( basename );
3210                 if (!add && !dyntexture)
3211                         return NULL;
3212                 if (item->merged == item->base)
3213                         item->merged = NULL;
3214                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3215                 R_PurgeTexture(item->stain );item->stain  = NULL;
3216                 R_PurgeTexture(item->merged);item->merged = NULL;
3217                 R_PurgeTexture(item->base  );item->base   = NULL;
3218                 R_PurgeTexture(item->pants );item->pants  = NULL;
3219                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3220                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3221                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3222                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3223                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3224         R_PurgeTexture(item->reflect);item->reflect = NULL;
3225                 item->loadsequence = 0;
3226         }
3227         else if( item->base == NULL )
3228         {
3229                 rtexture_t *dyntexture;
3230                 // check whether its a dynamic texture
3231                 // 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]
3232                 dyntexture = CL_GetDynTexture( basename );
3233                 item->base = dyntexture; // either NULL or dyntexture handle
3234         }
3235
3236         R_SkinFrame_MarkUsed(item);
3237         return item;
3238 }
3239
3240 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3241         { \
3242                 unsigned long long avgcolor[5], wsum; \
3243                 int pix, comp, w; \
3244                 avgcolor[0] = 0; \
3245                 avgcolor[1] = 0; \
3246                 avgcolor[2] = 0; \
3247                 avgcolor[3] = 0; \
3248                 avgcolor[4] = 0; \
3249                 wsum = 0; \
3250                 for(pix = 0; pix < cnt; ++pix) \
3251                 { \
3252                         w = 0; \
3253                         for(comp = 0; comp < 3; ++comp) \
3254                                 w += getpixel; \
3255                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3256                         { \
3257                                 ++wsum; \
3258                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3259                                 w = getpixel; \
3260                                 for(comp = 0; comp < 3; ++comp) \
3261                                         avgcolor[comp] += getpixel * w; \
3262                                 avgcolor[3] += w; \
3263                         } \
3264                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3265                         avgcolor[4] += getpixel; \
3266                 } \
3267                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3268                         avgcolor[3] = 1; \
3269                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3270                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3272                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3273         }
3274
3275 extern cvar_t gl_picmip;
3276 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3277 {
3278         int j;
3279         unsigned char *pixels;
3280         unsigned char *bumppixels;
3281         unsigned char *basepixels = NULL;
3282         int basepixels_width = 0;
3283         int basepixels_height = 0;
3284         skinframe_t *skinframe;
3285         rtexture_t *ddsbase = NULL;
3286         qboolean ddshasalpha = false;
3287         float ddsavgcolor[4];
3288         char basename[MAX_QPATH];
3289         int miplevel = R_PicmipForFlags(textureflags);
3290         int savemiplevel = miplevel;
3291         int mymiplevel;
3292
3293         if (cls.state == ca_dedicated)
3294                 return NULL;
3295
3296         // return an existing skinframe if already loaded
3297         // if loading of the first image fails, don't make a new skinframe as it
3298         // would cause all future lookups of this to be missing
3299         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3300         if (skinframe && skinframe->base)
3301                 return skinframe;
3302
3303         Image_StripImageExtension(name, basename, sizeof(basename));
3304
3305         // check for DDS texture file first
3306         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3307         {
3308                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3309                 if (basepixels == NULL)
3310                         return NULL;
3311         }
3312
3313         // FIXME handle miplevel
3314
3315         if (developer_loading.integer)
3316                 Con_Printf("loading skin \"%s\"\n", name);
3317
3318         // we've got some pixels to store, so really allocate this new texture now
3319         if (!skinframe)
3320                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3321         textureflags &= ~TEXF_FORCE_RELOAD;
3322         skinframe->stain = NULL;
3323         skinframe->merged = NULL;
3324         skinframe->base = NULL;
3325         skinframe->pants = NULL;
3326         skinframe->shirt = NULL;
3327         skinframe->nmap = NULL;
3328         skinframe->gloss = NULL;
3329         skinframe->glow = NULL;
3330         skinframe->fog = NULL;
3331         skinframe->reflect = NULL;
3332         skinframe->hasalpha = false;
3333
3334         if (ddsbase)
3335         {
3336                 skinframe->base = ddsbase;
3337                 skinframe->hasalpha = ddshasalpha;
3338                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3339                 if (r_loadfog && skinframe->hasalpha)
3340                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3341                 //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]);
3342         }
3343         else
3344         {
3345                 basepixels_width = image_width;
3346                 basepixels_height = image_height;
3347                 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);
3348                 if (textureflags & TEXF_ALPHA)
3349                 {
3350                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3351                         {
3352                                 if (basepixels[j] < 255)
3353                                 {
3354                                         skinframe->hasalpha = true;
3355                                         break;
3356                                 }
3357                         }
3358                         if (r_loadfog && skinframe->hasalpha)
3359                         {
3360                                 // has transparent pixels
3361                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3362                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3363                                 {
3364                                         pixels[j+0] = 255;
3365                                         pixels[j+1] = 255;
3366                                         pixels[j+2] = 255;
3367                                         pixels[j+3] = basepixels[j+3];
3368                                 }
3369                                 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);
3370                                 Mem_Free(pixels);
3371                         }
3372                 }
3373                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3374 #ifndef USE_GLES2
3375                 //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]);
3376                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3377                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3378                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3379                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3380 #endif
3381         }
3382
3383         if (r_loaddds)
3384         {
3385                 mymiplevel = savemiplevel;
3386                 if (r_loadnormalmap)
3387                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3388                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3389                 if (r_loadgloss)
3390                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3391                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3392                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3393                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3394         }
3395
3396         // _norm is the name used by tenebrae and has been adopted as standard
3397         if (r_loadnormalmap && skinframe->nmap == NULL)
3398         {
3399                 mymiplevel = savemiplevel;
3400                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3401                 {
3402                         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);
3403                         Mem_Free(pixels);
3404                         pixels = NULL;
3405                 }
3406                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3407                 {
3408                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3409                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3410                         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);
3411                         Mem_Free(pixels);
3412                         Mem_Free(bumppixels);
3413                 }
3414                 else if (r_shadow_bumpscale_basetexture.value > 0)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3418                         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);
3419                         Mem_Free(pixels);
3420                 }
3421 #ifndef USE_GLES2
3422                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3423                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3424 #endif
3425         }
3426
3427         // _luma is supported only for tenebrae compatibility
3428         // _glow is the preferred name
3429         mymiplevel = savemiplevel;
3430         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))))
3431         {
3432                 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);
3433 #ifndef USE_GLES2
3434                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3435                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3436 #endif
3437                 Mem_Free(pixels);pixels = NULL;
3438         }
3439
3440         mymiplevel = savemiplevel;
3441         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3442         {
3443                 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);
3444 #ifndef USE_GLES2
3445                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3446                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3447 #endif
3448                 Mem_Free(pixels);
3449                 pixels = NULL;
3450         }
3451
3452         mymiplevel = savemiplevel;
3453         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3454         {
3455                 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);
3456 #ifndef USE_GLES2
3457                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3458                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3459 #endif
3460                 Mem_Free(pixels);
3461                 pixels = NULL;
3462         }
3463
3464         mymiplevel = savemiplevel;
3465         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3466         {
3467                 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);
3468 #ifndef USE_GLES2
3469                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3470                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3471 #endif
3472                 Mem_Free(pixels);
3473                 pixels = NULL;
3474         }
3475
3476         mymiplevel = savemiplevel;
3477         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3478         {
3479                 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);
3480 #ifndef USE_GLES2
3481                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3482                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3483 #endif
3484                 Mem_Free(pixels);
3485                 pixels = NULL;
3486         }
3487
3488         if (basepixels)
3489                 Mem_Free(basepixels);
3490
3491         return skinframe;
3492 }
3493
3494 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3495 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3496 {
3497         int i;
3498         unsigned char *temp1, *temp2;
3499         skinframe_t *skinframe;
3500
3501         if (cls.state == ca_dedicated)
3502                 return NULL;
3503
3504         // if already loaded just return it, otherwise make a new skinframe
3505         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3506         if (skinframe && skinframe->base)
3507                 return skinframe;
3508         textureflags &= ~TEXF_FORCE_RELOAD;
3509
3510         skinframe->stain = NULL;
3511         skinframe->merged = NULL;
3512         skinframe->base = NULL;
3513         skinframe->pants = NULL;
3514         skinframe->shirt = NULL;
3515         skinframe->nmap = NULL;
3516         skinframe->gloss = NULL;
3517         skinframe->glow = NULL;
3518         skinframe->fog = NULL;
3519         skinframe->reflect = NULL;
3520         skinframe->hasalpha = false;
3521
3522         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3523         if (!skindata)
3524                 return NULL;
3525
3526         if (developer_loading.integer)
3527                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3528
3529         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3530         {
3531                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3532                 temp2 = temp1 + width * height * 4;
3533                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3534                 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);
3535                 Mem_Free(temp1);
3536         }
3537         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3538         if (textureflags & TEXF_ALPHA)
3539         {
3540                 for (i = 3;i < width * height * 4;i += 4)
3541                 {
3542                         if (skindata[i] < 255)
3543                         {
3544                                 skinframe->hasalpha = true;
3545                                 break;
3546                         }
3547                 }
3548                 if (r_loadfog && skinframe->hasalpha)
3549                 {
3550                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3551                         memcpy(fogpixels, skindata, width * height * 4);
3552                         for (i = 0;i < width * height * 4;i += 4)
3553                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3554                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3555                         Mem_Free(fogpixels);
3556                 }
3557         }
3558
3559         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3560         //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]);
3561
3562         return skinframe;
3563 }
3564
3565 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3566 {
3567         int i;
3568         int featuresmask;
3569         skinframe_t *skinframe;
3570
3571         if (cls.state == ca_dedicated)
3572                 return NULL;
3573
3574         // if already loaded just return it, otherwise make a new skinframe
3575         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3576         if (skinframe && skinframe->base)
3577                 return skinframe;
3578         textureflags &= ~TEXF_FORCE_RELOAD;
3579
3580         skinframe->stain = NULL;
3581         skinframe->merged = NULL;
3582         skinframe->base = NULL;
3583         skinframe->pants = NULL;
3584         skinframe->shirt = NULL;
3585         skinframe->nmap = NULL;
3586         skinframe->gloss = NULL;
3587         skinframe->glow = NULL;
3588         skinframe->fog = NULL;
3589         skinframe->reflect = NULL;
3590         skinframe->hasalpha = false;
3591
3592         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3593         if (!skindata)
3594                 return NULL;
3595
3596         if (developer_loading.integer)
3597                 Con_Printf("loading quake skin \"%s\"\n", name);
3598
3599         // 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)
3600         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3601         memcpy(skinframe->qpixels, skindata, width*height);
3602         skinframe->qwidth = width;
3603         skinframe->qheight = height;
3604
3605         featuresmask = 0;
3606         for (i = 0;i < width * height;i++)
3607                 featuresmask |= palette_featureflags[skindata[i]];
3608
3609         skinframe->hasalpha = false;
3610         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3611         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3612         skinframe->qgeneratemerged = true;
3613         skinframe->qgeneratebase = skinframe->qhascolormapping;
3614         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3615
3616         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3617         //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]);
3618
3619         return skinframe;
3620 }
3621
3622 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3623 {
3624         int width;
3625         int height;
3626         unsigned char *skindata;
3627
3628         if (!skinframe->qpixels)
3629                 return;
3630
3631         if (!skinframe->qhascolormapping)
3632                 colormapped = false;
3633
3634         if (colormapped)
3635         {
3636                 if (!skinframe->qgeneratebase)
3637                         return;
3638         }
3639         else
3640         {
3641                 if (!skinframe->qgeneratemerged)
3642                         return;
3643         }
3644
3645         width = skinframe->qwidth;
3646         height = skinframe->qheight;
3647         skindata = skinframe->qpixels;
3648
3649         if (skinframe->qgeneratenmap)
3650         {
3651                 unsigned char *temp1, *temp2;
3652                 skinframe->qgeneratenmap = false;
3653                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3654                 temp2 = temp1 + width * height * 4;
3655                 // use either a custom palette or the quake palette
3656                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3657                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3658                 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);
3659                 Mem_Free(temp1);
3660         }
3661
3662         if (skinframe->qgenerateglow)
3663         {
3664                 skinframe->qgenerateglow = false;
3665                 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
3666         }
3667
3668         if (colormapped)
3669         {
3670                 skinframe->qgeneratebase = false;
3671                 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);
3672                 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);
3673                 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);
3674         }
3675         else
3676         {
3677                 skinframe->qgeneratemerged = false;
3678                 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);
3679         }
3680
3681         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3682         {
3683                 Mem_Free(skinframe->qpixels);
3684                 skinframe->qpixels = NULL;
3685         }
3686 }
3687
3688 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)
3689 {
3690         int i;
3691         skinframe_t *skinframe;
3692
3693         if (cls.state == ca_dedicated)
3694                 return NULL;
3695
3696         // if already loaded just return it, otherwise make a new skinframe
3697         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3698         if (skinframe && skinframe->base)
3699                 return skinframe;
3700         textureflags &= ~TEXF_FORCE_RELOAD;
3701
3702         skinframe->stain = NULL;
3703         skinframe->merged = NULL;
3704         skinframe->base = NULL;
3705         skinframe->pants = NULL;
3706         skinframe->shirt = NULL;
3707         skinframe->nmap = NULL;
3708         skinframe->gloss = NULL;
3709         skinframe->glow = NULL;
3710         skinframe->fog = NULL;
3711         skinframe->reflect = NULL;
3712         skinframe->hasalpha = false;
3713
3714         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3715         if (!skindata)
3716                 return NULL;
3717
3718         if (developer_loading.integer)
3719                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3720
3721         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3722         if (textureflags & TEXF_ALPHA)
3723         {
3724                 for (i = 0;i < width * height;i++)
3725                 {
3726                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3727                         {
3728                                 skinframe->hasalpha = true;
3729                                 break;
3730                         }
3731                 }
3732                 if (r_loadfog && skinframe->hasalpha)
3733                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3734         }
3735
3736         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3737         //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]);
3738
3739         return skinframe;
3740 }
3741
3742 skinframe_t *R_SkinFrame_LoadMissing(void)
3743 {
3744         skinframe_t *skinframe;
3745
3746         if (cls.state == ca_dedicated)
3747                 return NULL;
3748
3749         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3750         skinframe->stain = NULL;
3751         skinframe->merged = NULL;
3752         skinframe->base = NULL;
3753         skinframe->pants = NULL;
3754         skinframe->shirt = NULL;
3755         skinframe->nmap = NULL;
3756         skinframe->gloss = NULL;
3757         skinframe->glow = NULL;
3758         skinframe->fog = NULL;
3759         skinframe->reflect = NULL;
3760         skinframe->hasalpha = false;
3761
3762         skinframe->avgcolor[0] = rand() / RAND_MAX;
3763         skinframe->avgcolor[1] = rand() / RAND_MAX;
3764         skinframe->avgcolor[2] = rand() / RAND_MAX;
3765         skinframe->avgcolor[3] = 1;
3766
3767         return skinframe;
3768 }
3769
3770 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3771 typedef struct suffixinfo_s
3772 {
3773         const char *suffix;
3774         qboolean flipx, flipy, flipdiagonal;
3775 }
3776 suffixinfo_t;
3777 static suffixinfo_t suffix[3][6] =
3778 {
3779         {
3780                 {"px",   false, false, false},
3781                 {"nx",   false, false, false},
3782                 {"py",   false, false, false},
3783                 {"ny",   false, false, false},
3784                 {"pz",   false, false, false},
3785                 {"nz",   false, false, false}
3786         },
3787         {
3788                 {"posx", false, false, false},
3789                 {"negx", false, false, false},
3790                 {"posy", false, false, false},
3791                 {"negy", false, false, false},
3792                 {"posz", false, false, false},
3793                 {"negz", false, false, false}
3794         },
3795         {
3796                 {"rt",    true, false,  true},
3797                 {"lf",   false,  true,  true},
3798                 {"ft",    true,  true, false},
3799                 {"bk",   false, false, false},
3800                 {"up",    true, false,  true},
3801                 {"dn",    true, false,  true}
3802         }
3803 };
3804
3805 static int componentorder[4] = {0, 1, 2, 3};
3806
3807 rtexture_t *R_LoadCubemap(const char *basename)
3808 {
3809         int i, j, cubemapsize;
3810         unsigned char *cubemappixels, *image_buffer;
3811         rtexture_t *cubemaptexture;
3812         char name[256];
3813         // must start 0 so the first loadimagepixels has no requested width/height
3814         cubemapsize = 0;
3815         cubemappixels = NULL;
3816         cubemaptexture = NULL;
3817         // keep trying different suffix groups (posx, px, rt) until one loads
3818         for (j = 0;j < 3 && !cubemappixels;j++)
3819         {
3820                 // load the 6 images in the suffix group
3821                 for (i = 0;i < 6;i++)
3822                 {
3823                         // generate an image name based on the base and and suffix
3824                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3825                         // load it
3826                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3827                         {
3828                                 // an image loaded, make sure width and height are equal
3829                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3830                                 {
3831                                         // if this is the first image to load successfully, allocate the cubemap memory
3832                                         if (!cubemappixels && image_width >= 1)
3833                                         {
3834                                                 cubemapsize = image_width;
3835                                                 // note this clears to black, so unavailable sides are black
3836                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3837                                         }
3838                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3839                                         if (cubemappixels)
3840                                                 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);
3841                                 }
3842                                 else
3843                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3844                                 // free the image
3845                                 Mem_Free(image_buffer);
3846                         }
3847                 }
3848         }
3849         // if a cubemap loaded, upload it
3850         if (cubemappixels)
3851         {
3852                 if (developer_loading.integer)
3853                         Con_Printf("loading cubemap \"%s\"\n", basename);
3854
3855                 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);
3856                 Mem_Free(cubemappixels);
3857         }
3858         else
3859         {
3860                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3861                 if (developer_loading.integer)
3862                 {
3863                         Con_Printf("(tried tried images ");
3864                         for (j = 0;j < 3;j++)
3865                                 for (i = 0;i < 6;i++)
3866                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3867                         Con_Print(" and was unable to find any of them).\n");
3868                 }
3869         }
3870         return cubemaptexture;
3871 }
3872
3873 rtexture_t *R_GetCubemap(const char *basename)
3874 {
3875         int i;
3876         for (i = 0;i < r_texture_numcubemaps;i++)
3877                 if (r_texture_cubemaps[i] != NULL)
3878                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3879                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3880         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3881                 return r_texture_whitecube;
3882         r_texture_numcubemaps++;
3883         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3884         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3885         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3886         return r_texture_cubemaps[i]->texture;
3887 }
3888
3889 void R_FreeCubemap(const char *basename)
3890 {
3891         int i;
3892
3893         for (i = 0;i < r_texture_numcubemaps;i++)
3894         {
3895                 if (r_texture_cubemaps[i] != NULL)
3896                 {
3897                         if (r_texture_cubemaps[i]->texture)
3898                         {
3899                                 if (developer_loading.integer)
3900                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3901                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3902                                 Mem_Free(r_texture_cubemaps[i]);
3903                                 r_texture_cubemaps[i] = NULL;
3904                         }
3905                 }
3906         }
3907 }
3908
3909 void R_FreeCubemaps(void)
3910 {
3911         int i;
3912         for (i = 0;i < r_texture_numcubemaps;i++)
3913         {
3914                 if (developer_loading.integer)
3915                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3916                 if (r_texture_cubemaps[i] != NULL)
3917                 {
3918                         if (r_texture_cubemaps[i]->texture)
3919                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3920                         Mem_Free(r_texture_cubemaps[i]);
3921                 }
3922         }
3923         r_texture_numcubemaps = 0;
3924 }
3925
3926 void R_Main_FreeViewCache(void)
3927 {
3928         if (r_refdef.viewcache.entityvisible)
3929                 Mem_Free(r_refdef.viewcache.entityvisible);
3930         if (r_refdef.viewcache.world_pvsbits)
3931                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3932         if (r_refdef.viewcache.world_leafvisible)
3933                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3934         if (r_refdef.viewcache.world_surfacevisible)
3935                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3937 }
3938
3939 void R_Main_ResizeViewCache(void)
3940 {
3941         int numentities = r_refdef.scene.numentities;
3942         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3943         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3944         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3945         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3946         if (r_refdef.viewcache.maxentities < numentities)
3947         {
3948                 r_refdef.viewcache.maxentities = numentities;
3949                 if (r_refdef.viewcache.entityvisible)
3950                         Mem_Free(r_refdef.viewcache.entityvisible);
3951                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3952         }
3953         if (r_refdef.viewcache.world_numclusters != numclusters)
3954         {
3955                 r_refdef.viewcache.world_numclusters = numclusters;
3956                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3957                 if (r_refdef.viewcache.world_pvsbits)
3958                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3959                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3960         }
3961         if (r_refdef.viewcache.world_numleafs != numleafs)
3962         {
3963                 r_refdef.viewcache.world_numleafs = numleafs;
3964                 if (r_refdef.viewcache.world_leafvisible)
3965                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3966                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3967         }
3968         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3969         {
3970                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3971                 if (r_refdef.viewcache.world_surfacevisible)
3972                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3973                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3974         }
3975 }
3976
3977 extern rtexture_t *loadingscreentexture;
3978 void gl_main_start(void)
3979 {
3980         loadingscreentexture = NULL;
3981         r_texture_blanknormalmap = NULL;
3982         r_texture_white = NULL;
3983         r_texture_grey128 = NULL;
3984         r_texture_black = NULL;
3985         r_texture_whitecube = NULL;
3986         r_texture_normalizationcube = NULL;
3987         r_texture_fogattenuation = NULL;
3988         r_texture_fogheighttexture = NULL;
3989         r_texture_gammaramps = NULL;
3990         r_texture_numcubemaps = 0;
3991
3992         r_loaddds = r_texture_dds_load.integer != 0;
3993         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3994
3995         switch(vid.renderpath)
3996         {
3997         case RENDERPATH_GL20:
3998         case RENDERPATH_D3D9:
3999         case RENDERPATH_D3D10:
4000         case RENDERPATH_D3D11:
4001         case RENDERPATH_SOFT:
4002         case RENDERPATH_GLES2:
4003                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4004                 Cvar_SetValueQuick(&gl_combine, 1);
4005                 Cvar_SetValueQuick(&r_glsl, 1);
4006                 r_loadnormalmap = true;
4007                 r_loadgloss = true;
4008                 r_loadfog = false;
4009                 break;
4010         case RENDERPATH_GL13:
4011         case RENDERPATH_GLES1:
4012                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4013                 Cvar_SetValueQuick(&gl_combine, 1);
4014                 Cvar_SetValueQuick(&r_glsl, 0);
4015                 r_loadnormalmap = false;
4016                 r_loadgloss = false;
4017                 r_loadfog = true;
4018                 break;
4019         case RENDERPATH_GL11:
4020                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4021                 Cvar_SetValueQuick(&gl_combine, 0);
4022                 Cvar_SetValueQuick(&r_glsl, 0);
4023                 r_loadnormalmap = false;
4024                 r_loadgloss = false;
4025                 r_loadfog = true;
4026                 break;
4027         }
4028
4029         R_AnimCache_Free();
4030         R_FrameData_Reset();
4031
4032         r_numqueries = 0;
4033         r_maxqueries = 0;
4034         memset(r_queries, 0, sizeof(r_queries));
4035
4036         r_qwskincache = NULL;
4037         r_qwskincache_size = 0;
4038
4039         // due to caching of texture_t references, the collision cache must be reset
4040         Collision_Cache_Reset(true);
4041
4042         // set up r_skinframe loading system for textures
4043         memset(&r_skinframe, 0, sizeof(r_skinframe));
4044         r_skinframe.loadsequence = 1;
4045         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4046
4047         r_main_texturepool = R_AllocTexturePool();
4048         R_BuildBlankTextures();
4049         R_BuildNoTexture();
4050         if (vid.support.arb_texture_cube_map)
4051         {
4052                 R_BuildWhiteCube();
4053                 R_BuildNormalizationCube();
4054         }
4055         r_texture_fogattenuation = NULL;
4056         r_texture_fogheighttexture = NULL;
4057         r_texture_gammaramps = NULL;
4058         //r_texture_fogintensity = NULL;
4059         memset(&r_fb, 0, sizeof(r_fb));
4060         r_glsl_permutation = NULL;
4061         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4062         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4063         glslshaderstring = NULL;
4064 #ifdef SUPPORTD3D
4065         r_hlsl_permutation = NULL;
4066         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4067         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4068 #endif
4069         hlslshaderstring = NULL;
4070         memset(&r_svbsp, 0, sizeof (r_svbsp));
4071
4072         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4073         r_texture_numcubemaps = 0;
4074
4075         r_refdef.fogmasktable_density = 0;
4076 }
4077
4078 void gl_main_shutdown(void)
4079 {
4080         R_AnimCache_Free();
4081         R_FrameData_Reset();
4082
4083         R_Main_FreeViewCache();
4084
4085         switch(vid.renderpath)
4086         {
4087         case RENDERPATH_GL11:
4088         case RENDERPATH_GL13:
4089         case RENDERPATH_GL20:
4090         case RENDERPATH_GLES1:
4091         case RENDERPATH_GLES2:
4092 #ifdef GL_SAMPLES_PASSED_ARB
4093                 if (r_maxqueries)
4094                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4095 #endif
4096                 break;
4097         case RENDERPATH_D3D9:
4098                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4099                 break;
4100         case RENDERPATH_D3D10:
4101                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4102                 break;
4103         case RENDERPATH_D3D11:
4104                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4105                 break;
4106         case RENDERPATH_SOFT:
4107                 break;
4108         }
4109
4110         r_numqueries = 0;
4111         r_maxqueries = 0;
4112         memset(r_queries, 0, sizeof(r_queries));
4113
4114         r_qwskincache = NULL;
4115         r_qwskincache_size = 0;
4116
4117         // clear out the r_skinframe state
4118         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4119         memset(&r_skinframe, 0, sizeof(r_skinframe));
4120
4121         if (r_svbsp.nodes)
4122                 Mem_Free(r_svbsp.nodes);
4123         memset(&r_svbsp, 0, sizeof (r_svbsp));
4124         R_FreeTexturePool(&r_main_texturepool);
4125         loadingscreentexture = NULL;
4126         r_texture_blanknormalmap = NULL;
4127         r_texture_white = NULL;
4128         r_texture_grey128 = NULL;
4129         r_texture_black = NULL;
4130         r_texture_whitecube = NULL;
4131         r_texture_normalizationcube = NULL;
4132         r_texture_fogattenuation = NULL;
4133         r_texture_fogheighttexture = NULL;
4134         r_texture_gammaramps = NULL;
4135         r_texture_numcubemaps = 0;
4136         //r_texture_fogintensity = NULL;
4137         memset(&r_fb, 0, sizeof(r_fb));
4138         R_GLSL_Restart_f();
4139
4140         r_glsl_permutation = NULL;
4141         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4142         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4143         glslshaderstring = NULL;
4144 #ifdef SUPPORTD3D
4145         r_hlsl_permutation = NULL;
4146         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4147         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4148 #endif
4149         hlslshaderstring = NULL;
4150 }
4151
4152 extern void CL_ParseEntityLump(char *entitystring);
4153 void gl_main_newmap(void)
4154 {
4155         // FIXME: move this code to client
4156         char *entities, entname[MAX_QPATH];
4157         if (r_qwskincache)
4158                 Mem_Free(r_qwskincache);
4159         r_qwskincache = NULL;
4160         r_qwskincache_size = 0;
4161         if (cl.worldmodel)
4162         {
4163                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4164                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4165                 {
4166                         CL_ParseEntityLump(entities);
4167                         Mem_Free(entities);
4168                         return;
4169                 }
4170                 if (cl.worldmodel->brush.entities)
4171                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4172         }
4173         R_Main_FreeViewCache();
4174
4175         R_FrameData_Reset();
4176 }
4177
4178 void GL_Main_Init(void)
4179 {
4180         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4181
4182         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4183         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4184         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4185         if (gamemode == GAME_NEHAHRA)
4186         {
4187                 Cvar_RegisterVariable (&gl_fogenable);
4188                 Cvar_RegisterVariable (&gl_fogdensity);
4189                 Cvar_RegisterVariable (&gl_fogred);
4190                 Cvar_RegisterVariable (&gl_foggreen);
4191                 Cvar_RegisterVariable (&gl_fogblue);
4192                 Cvar_RegisterVariable (&gl_fogstart);
4193                 Cvar_RegisterVariable (&gl_fogend);
4194                 Cvar_RegisterVariable (&gl_skyclip);
4195         }
4196         Cvar_RegisterVariable(&r_motionblur);
4197         Cvar_RegisterVariable(&r_damageblur);
4198         Cvar_RegisterVariable(&r_motionblur_averaging);
4199         Cvar_RegisterVariable(&r_motionblur_randomize);
4200         Cvar_RegisterVariable(&r_motionblur_minblur);
4201         Cvar_RegisterVariable(&r_motionblur_maxblur);
4202         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4203         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4204         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4205         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4206         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4207         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4208         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4209         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4210         Cvar_RegisterVariable(&r_equalize_entities_by);
4211         Cvar_RegisterVariable(&r_equalize_entities_to);
4212         Cvar_RegisterVariable(&r_depthfirst);
4213         Cvar_RegisterVariable(&r_useinfinitefarclip);
4214         Cvar_RegisterVariable(&r_farclip_base);
4215         Cvar_RegisterVariable(&r_farclip_world);
4216         Cvar_RegisterVariable(&r_nearclip);
4217         Cvar_RegisterVariable(&r_deformvertexes);
4218         Cvar_RegisterVariable(&r_transparent);
4219         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4220         Cvar_RegisterVariable(&r_showoverdraw);
4221         Cvar_RegisterVariable(&r_showbboxes);
4222         Cvar_RegisterVariable(&r_showsurfaces);
4223         Cvar_RegisterVariable(&r_showtris);
4224         Cvar_RegisterVariable(&r_shownormals);
4225         Cvar_RegisterVariable(&r_showlighting);
4226         Cvar_RegisterVariable(&r_showshadowvolumes);
4227         Cvar_RegisterVariable(&r_showcollisionbrushes);
4228         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4229         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4230         Cvar_RegisterVariable(&r_showdisabledepthtest);
4231         Cvar_RegisterVariable(&r_drawportals);
4232         Cvar_RegisterVariable(&r_drawentities);
4233         Cvar_RegisterVariable(&r_draw2d);
4234         Cvar_RegisterVariable(&r_drawworld);
4235         Cvar_RegisterVariable(&r_cullentities_trace);
4236         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4237         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4238         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4239         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4240         Cvar_RegisterVariable(&r_sortentities);
4241         Cvar_RegisterVariable(&r_drawviewmodel);
4242         Cvar_RegisterVariable(&r_drawexteriormodel);
4243         Cvar_RegisterVariable(&r_speeds);
4244         Cvar_RegisterVariable(&r_fullbrights);
4245         Cvar_RegisterVariable(&r_wateralpha);
4246         Cvar_RegisterVariable(&r_dynamic);
4247         Cvar_RegisterVariable(&r_fakelight);
4248         Cvar_RegisterVariable(&r_fakelight_intensity);
4249         Cvar_RegisterVariable(&r_fullbright);
4250         Cvar_RegisterVariable(&r_shadows);
4251         Cvar_RegisterVariable(&r_shadows_darken);
4252         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4253         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4254         Cvar_RegisterVariable(&r_shadows_throwdistance);
4255         Cvar_RegisterVariable(&r_shadows_throwdirection);
4256         Cvar_RegisterVariable(&r_shadows_focus);
4257         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4258         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4259         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4260         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4261         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4262         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4263         Cvar_RegisterVariable(&r_fog_exp2);
4264         Cvar_RegisterVariable(&r_fog_clear);
4265         Cvar_RegisterVariable(&r_drawfog);
4266         Cvar_RegisterVariable(&r_transparentdepthmasking);
4267         Cvar_RegisterVariable(&r_transparent_sortmindist);
4268         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4269         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4270         Cvar_RegisterVariable(&r_texture_dds_load);
4271         Cvar_RegisterVariable(&r_texture_dds_save);
4272         Cvar_RegisterVariable(&r_textureunits);
4273         Cvar_RegisterVariable(&gl_combine);
4274         Cvar_RegisterVariable(&r_viewfbo);
4275         Cvar_RegisterVariable(&r_viewscale);
4276         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4277         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4278         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4279         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4280         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4281         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4282         Cvar_RegisterVariable(&r_glsl);
4283         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4284         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4285         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4286         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4287         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4288         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4289         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4290         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4291         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4292         Cvar_RegisterVariable(&r_glsl_postprocess);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4294         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4295         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4296         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4297         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4298         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4299         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4300         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4301
4302         Cvar_RegisterVariable(&r_water);
4303         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4304         Cvar_RegisterVariable(&r_water_clippingplanebias);
4305         Cvar_RegisterVariable(&r_water_refractdistort);
4306         Cvar_RegisterVariable(&r_water_reflectdistort);
4307         Cvar_RegisterVariable(&r_water_scissormode);
4308         Cvar_RegisterVariable(&r_water_lowquality);
4309         Cvar_RegisterVariable(&r_water_hideplayer);
4310         Cvar_RegisterVariable(&r_water_fbo);
4311
4312         Cvar_RegisterVariable(&r_lerpsprites);
4313         Cvar_RegisterVariable(&r_lerpmodels);
4314         Cvar_RegisterVariable(&r_lerplightstyles);
4315         Cvar_RegisterVariable(&r_waterscroll);
4316         Cvar_RegisterVariable(&r_bloom);
4317         Cvar_RegisterVariable(&r_bloom_colorscale);
4318         Cvar_RegisterVariable(&r_bloom_brighten);
4319         Cvar_RegisterVariable(&r_bloom_blur);
4320         Cvar_RegisterVariable(&r_bloom_resolution);
4321         Cvar_RegisterVariable(&r_bloom_colorexponent);
4322         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4323         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4324         Cvar_RegisterVariable(&r_hdr_glowintensity);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4327         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4328         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4329         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4330         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4331         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4332         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4333         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4334         Cvar_RegisterVariable(&developer_texturelogging);
4335         Cvar_RegisterVariable(&gl_lightmaps);
4336         Cvar_RegisterVariable(&r_test);
4337         Cvar_RegisterVariable(&r_glsl_saturation);
4338         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4339         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4340         Cvar_RegisterVariable(&r_framedatasize);
4341         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4342                 Cvar_SetValue("r_fullbrights", 0);
4343         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4344 }
4345
4346 extern void R_Textures_Init(void);
4347 extern void GL_Draw_Init(void);
4348 extern void GL_Main_Init(void);
4349 extern void R_Shadow_Init(void);
4350 extern void R_Sky_Init(void);
4351 extern void GL_Surf_Init(void);
4352 extern void R_Particles_Init(void);
4353 extern void R_Explosion_Init(void);
4354 extern void gl_backend_init(void);
4355 extern void Sbar_Init(void);
4356 extern void R_LightningBeams_Init(void);
4357 extern void Mod_RenderInit(void);
4358 extern void Font_Init(void);
4359
4360 void Render_Init(void)
4361 {
4362         gl_backend_init();
4363         R_Textures_Init();
4364         GL_Main_Init();
4365         Font_Init();
4366         GL_Draw_Init();
4367         R_Shadow_Init();
4368         R_Sky_Init();
4369         GL_Surf_Init();
4370         Sbar_Init();
4371         R_Particles_Init();
4372         R_Explosion_Init();
4373         R_LightningBeams_Init();
4374         Mod_RenderInit();
4375 }
4376
4377 /*
4378 ===============
4379 GL_Init
4380 ===============
4381 */
4382 #ifndef USE_GLES2
4383 extern char *ENGINE_EXTENSIONS;
4384 void GL_Init (void)
4385 {
4386         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4387         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4388         gl_version = (const char *)qglGetString(GL_VERSION);
4389         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4390
4391         if (!gl_extensions)
4392                 gl_extensions = "";
4393         if (!gl_platformextensions)
4394                 gl_platformextensions = "";
4395
4396         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4397         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4398         Con_Printf("GL_VERSION: %s\n", gl_version);
4399         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4400         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4401
4402         VID_CheckExtensions();
4403
4404         // LordHavoc: report supported extensions
4405         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4406
4407         // clear to black (loading plaque will be seen over this)
4408         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4409 }
4410 #endif
4411
4412 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4413 {
4414         int i;
4415         mplane_t *p;
4416         if (r_trippy.integer)
4417                 return false;
4418         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4419         {
4420                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4421                 if (i == 4)
4422                         continue;
4423                 p = r_refdef.view.frustum + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4465 {
4466         int i;
4467         const mplane_t *p;
4468         if (r_trippy.integer)
4469                 return false;
4470         for (i = 0;i < numplanes;i++)
4471         {
4472                 p = planes + i;
4473                 switch(p->signbits)
4474                 {
4475                 default:
4476                 case 0:
4477                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 1:
4481                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 case 2:
4485                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4486                                 return true;
4487                         break;
4488                 case 3:
4489                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4490                                 return true;
4491                         break;
4492                 case 4:
4493                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4494                                 return true;
4495                         break;
4496                 case 5:
4497                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4498                                 return true;
4499                         break;
4500                 case 6:
4501                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4502                                 return true;
4503                         break;
4504                 case 7:
4505                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4506                                 return true;
4507                         break;
4508                 }
4509         }
4510         return false;
4511 }
4512
4513 //==================================================================================
4514
4515 // LordHavoc: this stores temporary data used within the same frame
4516
4517 typedef struct r_framedata_mem_s
4518 {
4519         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4520         size_t size; // how much usable space
4521         size_t current; // how much space in use
4522         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4523         size_t wantedsize; // how much space was allocated
4524         unsigned char *data; // start of real data (16byte aligned)
4525 }
4526 r_framedata_mem_t;
4527
4528 static r_framedata_mem_t *r_framedata_mem;
4529
4530 void R_FrameData_Reset(void)
4531 {
4532         while (r_framedata_mem)
4533         {
4534                 r_framedata_mem_t *next = r_framedata_mem->purge;
4535                 Mem_Free(r_framedata_mem);
4536                 r_framedata_mem = next;
4537         }
4538 }
4539
4540 void R_FrameData_Resize(void)
4541 {
4542         size_t wantedsize;
4543         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4544         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4545         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4546         {
4547                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4548                 newmem->wantedsize = wantedsize;
4549                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4550                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4551                 newmem->current = 0;
4552                 newmem->mark = 0;
4553                 newmem->purge = r_framedata_mem;
4554                 r_framedata_mem = newmem;
4555         }
4556 }
4557
4558 void R_FrameData_NewFrame(void)
4559 {
4560         R_FrameData_Resize();
4561         if (!r_framedata_mem)
4562                 return;
4563         // if we ran out of space on the last frame, free the old memory now
4564         while (r_framedata_mem->purge)
4565         {
4566                 // repeatedly remove the second item in the list, leaving only head
4567                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4568                 Mem_Free(r_framedata_mem->purge);
4569                 r_framedata_mem->purge = next;
4570         }
4571         // reset the current mem pointer
4572         r_framedata_mem->current = 0;
4573         r_framedata_mem->mark = 0;
4574 }
4575
4576 void *R_FrameData_Alloc(size_t size)
4577 {
4578         void *data;
4579
4580         // align to 16 byte boundary - the data pointer is already aligned, so we
4581         // only need to ensure the size of every allocation is also aligned
4582         size = (size + 15) & ~15;
4583
4584         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4585         {
4586                 // emergency - we ran out of space, allocate more memory
4587                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4588                 R_FrameData_Resize();
4589         }
4590
4591         data = r_framedata_mem->data + r_framedata_mem->current;
4592         r_framedata_mem->current += size;
4593
4594         // count the usage for stats
4595         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4596         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4597
4598         return (void *)data;
4599 }
4600
4601 void *R_FrameData_Store(size_t size, void *data)
4602 {
4603         void *d = R_FrameData_Alloc(size);
4604         if (d && data)
4605                 memcpy(d, data, size);
4606         return d;
4607 }
4608
4609 void R_FrameData_SetMark(void)
4610 {
4611         if (!r_framedata_mem)
4612                 return;
4613         r_framedata_mem->mark = r_framedata_mem->current;
4614 }
4615
4616 void R_FrameData_ReturnToMark(void)
4617 {
4618         if (!r_framedata_mem)
4619                 return;
4620         r_framedata_mem->current = r_framedata_mem->mark;
4621 }
4622
4623 //==================================================================================
4624
4625 // LordHavoc: animcache originally written by Echon, rewritten since then
4626
4627 /**
4628  * Animation cache prevents re-generating mesh data for an animated model
4629  * multiple times in one frame for lighting, shadowing, reflections, etc.
4630  */
4631
4632 void R_AnimCache_Free(void)
4633 {
4634 }
4635
4636 void R_AnimCache_ClearCache(void)
4637 {
4638         int i;
4639         entity_render_t *ent;
4640
4641         for (i = 0;i < r_refdef.scene.numentities;i++)
4642         {
4643                 ent = r_refdef.scene.entities[i];
4644                 ent->animcache_vertex3f = NULL;
4645                 ent->animcache_normal3f = NULL;
4646                 ent->animcache_svector3f = NULL;
4647                 ent->animcache_tvector3f = NULL;
4648                 ent->animcache_vertexmesh = NULL;
4649                 ent->animcache_vertex3fbuffer = NULL;
4650                 ent->animcache_vertexmeshbuffer = NULL;
4651         }
4652 }
4653
4654 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4655 {
4656         int i;
4657
4658         // check if we need the meshbuffers
4659         if (!vid.useinterleavedarrays)
4660                 return;
4661
4662         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4663                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4664         // TODO: upload vertex3f buffer?
4665         if (ent->animcache_vertexmesh)
4666         {
4667                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4668                 for (i = 0;i < numvertices;i++)
4669                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4670                 if (ent->animcache_svector3f)
4671                         for (i = 0;i < numvertices;i++)
4672                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4673                 if (ent->animcache_tvector3f)
4674                         for (i = 0;i < numvertices;i++)
4675                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4676                 if (ent->animcache_normal3f)
4677                         for (i = 0;i < numvertices;i++)
4678                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4679                 // TODO: upload vertexmeshbuffer?
4680         }
4681 }
4682
4683 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4684 {
4685         dp_model_t *model = ent->model;
4686         int numvertices;
4687         // see if it's already cached this frame
4688         if (ent->animcache_vertex3f)
4689         {
4690                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4691                 if (wantnormals || wanttangents)
4692                 {
4693                         if (ent->animcache_normal3f)
4694                                 wantnormals = false;
4695                         if (ent->animcache_svector3f)
4696                                 wanttangents = false;
4697                         if (wantnormals || wanttangents)
4698                         {
4699                                 numvertices = model->surfmesh.num_vertices;
4700                                 if (wantnormals)
4701                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4702                                 if (wanttangents)
4703                                 {
4704                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4705                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4706                                 }
4707                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4708                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4709                         }
4710                 }
4711         }
4712         else
4713         {
4714                 // see if this ent is worth caching
4715                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4716                         return false;
4717                 // get some memory for this entity and generate mesh data
4718                 numvertices = model->surfmesh.num_vertices;
4719                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4720                 if (wantnormals)
4721                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4722                 if (wanttangents)
4723                 {
4724                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4726                 }
4727                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4728                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4729         }
4730         return true;
4731 }
4732
4733 void R_AnimCache_CacheVisibleEntities(void)
4734 {
4735         int i;
4736         qboolean wantnormals = true;
4737         qboolean wanttangents = !r_showsurfaces.integer;
4738
4739         switch(vid.renderpath)
4740         {
4741         case RENDERPATH_GL20:
4742         case RENDERPATH_D3D9:
4743         case RENDERPATH_D3D10:
4744         case RENDERPATH_D3D11:
4745         case RENDERPATH_GLES2:
4746                 break;
4747         case RENDERPATH_GL11:
4748         case RENDERPATH_GL13:
4749         case RENDERPATH_GLES1:
4750                 wanttangents = false;
4751                 break;
4752         case RENDERPATH_SOFT:
4753                 break;
4754         }
4755
4756         if (r_shownormals.integer)
4757                 wanttangents = wantnormals = true;
4758
4759         // TODO: thread this
4760         // NOTE: R_PrepareRTLights() also caches entities
4761
4762         for (i = 0;i < r_refdef.scene.numentities;i++)
4763                 if (r_refdef.viewcache.entityvisible[i])
4764                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4765 }
4766
4767 //==================================================================================
4768
4769 extern cvar_t r_overheadsprites_pushback;
4770
4771 static void R_View_UpdateEntityLighting (void)
4772 {
4773         int i;
4774         entity_render_t *ent;
4775         vec3_t tempdiffusenormal, avg;
4776         vec_t f, fa, fd, fdd;
4777         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4778
4779         for (i = 0;i < r_refdef.scene.numentities;i++)
4780         {
4781                 ent = r_refdef.scene.entities[i];
4782
4783                 // skip unseen models and models that updated by CSQC
4784                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4785                         continue;
4786
4787                 // skip bsp models
4788                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4789                 {
4790                         // TODO: use modellight for r_ambient settings on world?
4791                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4792                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4793                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4794                         continue;
4795                 }
4796
4797                 // fetch the lighting from the worldmodel data
4798                 VectorClear(ent->modellight_ambient);
4799                 VectorClear(ent->modellight_diffuse);
4800                 VectorClear(tempdiffusenormal);
4801                 if (ent->flags & RENDER_LIGHT)
4802                 {
4803                         vec3_t org;
4804                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4805
4806                         // complete lightning for lit sprites
4807                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4808                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4809                         {
4810                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4811                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4812                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4813                         }
4814                         else
4815                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4816
4817                         if(ent->flags & RENDER_EQUALIZE)
4818                         {
4819                                 // first fix up ambient lighting...
4820                                 if(r_equalize_entities_minambient.value > 0)
4821                                 {
4822                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4823                                         if(fd > 0)
4824                                         {
4825                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4826                                                 if(fa < r_equalize_entities_minambient.value * fd)
4827                                                 {
4828                                                         // solve:
4829                                                         //   fa'/fd' = minambient
4830                                                         //   fa'+0.25*fd' = fa+0.25*fd
4831                                                         //   ...
4832                                                         //   fa' = fd' * minambient
4833                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4834                                                         //   ...
4835                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4836                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4837                                                         //   ...
4838                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4839                                                         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
4840                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4841                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4842                                                 }
4843                                         }
4844                                 }
4845
4846                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4847                                 {
4848                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4849                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4850                                         f = fa + 0.25 * fd;
4851                                         if(f > 0)
4852                                         {
4853                                                 // adjust brightness and saturation to target
4854                                                 avg[0] = avg[1] = avg[2] = fa / f;
4855                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4856                                                 avg[0] = avg[1] = avg[2] = fd / f;
4857                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4858                                         }
4859                                 }
4860                         }
4861                 }
4862                 else // highly rare
4863                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4864
4865                 // move the light direction into modelspace coordinates for lighting code
4866                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4867                 if(VectorLength2(ent->modellight_lightdir) == 0)
4868                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4869                 VectorNormalize(ent->modellight_lightdir);
4870         }
4871 }
4872
4873 #define MAX_LINEOFSIGHTTRACES 64
4874
4875 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4876 {
4877         int i;
4878         vec3_t boxmins, boxmaxs;
4879         vec3_t start;
4880         vec3_t end;
4881         dp_model_t *model = r_refdef.scene.worldmodel;
4882
4883         if (!model || !model->brush.TraceLineOfSight)
4884                 return true;
4885
4886         // expand the box a little
4887         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4888         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4889         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4890         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4891         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4892         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4893
4894         // return true if eye is inside enlarged box
4895         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4896                 return true;
4897
4898         // try center
4899         VectorCopy(eye, start);
4900         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4901         if (model->brush.TraceLineOfSight(model, start, end))
4902                 return true;
4903
4904         // try various random positions
4905         for (i = 0;i < numsamples;i++)
4906         {
4907                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4908                 if (model->brush.TraceLineOfSight(model, start, end))
4909                         return true;
4910         }
4911
4912         return false;
4913 }
4914
4915
4916 static void R_View_UpdateEntityVisible (void)
4917 {
4918         int i;
4919         int renderimask;
4920         int samples;
4921         entity_render_t *ent;
4922
4923         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4924                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4925                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4926                 :                                                          RENDER_EXTERIORMODEL;
4927         if (!r_drawviewmodel.integer)
4928                 renderimask |= RENDER_VIEWMODEL;
4929         if (!r_drawexteriormodel.integer)
4930                 renderimask |= RENDER_EXTERIORMODEL;
4931         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4932         {
4933                 // worldmodel can check visibility
4934                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4935                 for (i = 0;i < r_refdef.scene.numentities;i++)
4936                 {
4937                         ent = r_refdef.scene.entities[i];
4938                         if (!(ent->flags & renderimask))
4939                         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)))
4940                         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))
4941                                 r_refdef.viewcache.entityvisible[i] = true;
4942                 }
4943         }
4944         else
4945         {
4946                 // no worldmodel or it can't check visibility
4947                 for (i = 0;i < r_refdef.scene.numentities;i++)
4948                 {
4949                         ent = r_refdef.scene.entities[i];
4950                         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));
4951                 }
4952         }
4953         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4954                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4955         {
4956                 for (i = 0;i < r_refdef.scene.numentities;i++)
4957                 {
4958                         if (!r_refdef.viewcache.entityvisible[i])
4959                                 continue;
4960                         ent = r_refdef.scene.entities[i];
4961                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4962                         {
4963                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4964                                 if (samples < 0)
4965                                         continue; // temp entities do pvs only
4966                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4967                                         ent->last_trace_visibility = realtime;
4968                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4969                                         r_refdef.viewcache.entityvisible[i] = 0;
4970                         }
4971                 }
4972         }
4973 }
4974
4975 /// only used if skyrendermasked, and normally returns false
4976 int R_DrawBrushModelsSky (void)
4977 {
4978         int i, sky;
4979         entity_render_t *ent;
4980
4981         sky = false;
4982         for (i = 0;i < r_refdef.scene.numentities;i++)
4983         {
4984                 if (!r_refdef.viewcache.entityvisible[i])
4985                         continue;
4986                 ent = r_refdef.scene.entities[i];
4987                 if (!ent->model || !ent->model->DrawSky)
4988                         continue;
4989                 ent->model->DrawSky(ent);
4990                 sky = true;
4991         }
4992         return sky;
4993 }
4994
4995 static void R_DrawNoModel(entity_render_t *ent);
4996 static void R_DrawModels(void)
4997 {
4998         int i;
4999         entity_render_t *ent;
5000
5001         for (i = 0;i < r_refdef.scene.numentities;i++)
5002         {
5003                 if (!r_refdef.viewcache.entityvisible[i])
5004                         continue;
5005                 ent = r_refdef.scene.entities[i];
5006                 r_refdef.stats.entities++;
5007                 /*
5008                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5009                 {
5010                         vec3_t f, l, u, o;
5011                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5012                         Con_Printf("R_DrawModels\n");
5013                         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]);
5014                         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);
5015                         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);
5016                 }
5017                 */
5018                 if (ent->model && ent->model->Draw != NULL)
5019                         ent->model->Draw(ent);
5020                 else
5021                         R_DrawNoModel(ent);
5022         }
5023 }
5024
5025 static void R_DrawModelsDepth(void)
5026 {
5027         int i;
5028         entity_render_t *ent;
5029
5030         for (i = 0;i < r_refdef.scene.numentities;i++)
5031         {
5032                 if (!r_refdef.viewcache.entityvisible[i])
5033                         continue;
5034                 ent = r_refdef.scene.entities[i];
5035                 if (ent->model && ent->model->DrawDepth != NULL)
5036                         ent->model->DrawDepth(ent);
5037         }
5038 }
5039
5040 static void R_DrawModelsDebug(void)
5041 {
5042         int i;
5043         entity_render_t *ent;
5044
5045         for (i = 0;i < r_refdef.scene.numentities;i++)
5046         {
5047                 if (!r_refdef.viewcache.entityvisible[i])
5048                         continue;
5049                 ent = r_refdef.scene.entities[i];
5050                 if (ent->model && ent->model->DrawDebug != NULL)
5051                         ent->model->DrawDebug(ent);
5052         }
5053 }
5054
5055 static void R_DrawModelsAddWaterPlanes(void)
5056 {
5057         int i;
5058         entity_render_t *ent;
5059
5060         for (i = 0;i < r_refdef.scene.numentities;i++)
5061         {
5062                 if (!r_refdef.viewcache.entityvisible[i])
5063                         continue;
5064                 ent = r_refdef.scene.entities[i];
5065                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5066                         ent->model->DrawAddWaterPlanes(ent);
5067         }
5068 }
5069
5070 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}};
5071
5072 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5073 {
5074         if (r_hdr_irisadaptation.integer)
5075         {
5076                 vec3_t p;
5077                 vec3_t ambient;
5078                 vec3_t diffuse;
5079                 vec3_t diffusenormal;
5080                 vec3_t forward;
5081                 vec_t brightness = 0.0f;
5082                 vec_t goal;
5083                 vec_t current;
5084                 vec_t d;
5085                 int c;
5086                 VectorCopy(r_refdef.view.forward, forward);
5087                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5088                 {
5089                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5090                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5091                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5092                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5093                         d = DotProduct(forward, diffusenormal);
5094                         brightness += VectorLength(ambient);
5095                         if (d > 0)
5096                                 brightness += d * VectorLength(diffuse);
5097                 }
5098                 brightness *= 1.0f / c;
5099                 brightness += 0.00001f; // make sure it's never zero
5100                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5101                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5102                 current = r_hdr_irisadaptation_value.value;
5103                 if (current < goal)
5104                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5105                 else if (current > goal)
5106                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5107                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5108                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5109         }
5110         else if (r_hdr_irisadaptation_value.value != 1.0f)
5111                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5112 }
5113
5114 static void R_View_SetFrustum(const int *scissor)
5115 {
5116         int i;
5117         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5118         vec3_t forward, left, up, origin, v;
5119
5120         if(scissor)
5121         {
5122                 // flipped x coordinates (because x points left here)
5123                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5124                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5125
5126                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5127                 switch(vid.renderpath)
5128                 {
5129                         case RENDERPATH_D3D9:
5130                         case RENDERPATH_D3D10:
5131                         case RENDERPATH_D3D11:
5132                                 // non-flipped y coordinates
5133                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5134                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5135                                 break;
5136                         case RENDERPATH_SOFT:
5137                         case RENDERPATH_GL11:
5138                         case RENDERPATH_GL13:
5139                         case RENDERPATH_GL20:
5140                         case RENDERPATH_GLES1:
5141                         case RENDERPATH_GLES2:
5142                                 // non-flipped y coordinates
5143                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5144                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5145                                 break;
5146                 }
5147         }
5148
5149         // we can't trust r_refdef.view.forward and friends in reflected scenes
5150         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5151
5152 #if 0
5153         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5154         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5155         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5156         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5157         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5158         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5159         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5160         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5161         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5162         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5163         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5164         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5165 #endif
5166
5167 #if 0
5168         zNear = r_refdef.nearclip;
5169         nudge = 1.0 - 1.0 / (1<<23);
5170         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5171         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5172         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5173         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5174         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5175         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5176         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5177         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5178 #endif
5179
5180
5181
5182 #if 0
5183         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5184         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5185         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5186         r_refdef.view.frustum[0].dist = m[15] - m[12];
5187
5188         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5189         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5190         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5191         r_refdef.view.frustum[1].dist = m[15] + m[12];
5192
5193         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5194         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5195         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5196         r_refdef.view.frustum[2].dist = m[15] - m[13];
5197
5198         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5199         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5200         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5201         r_refdef.view.frustum[3].dist = m[15] + m[13];
5202
5203         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5204         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5205         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5206         r_refdef.view.frustum[4].dist = m[15] - m[14];
5207
5208         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5209         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5210         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5211         r_refdef.view.frustum[5].dist = m[15] + m[14];
5212 #endif
5213
5214         if (r_refdef.view.useperspective)
5215         {
5216                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5217                 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]);
5218                 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]);
5219                 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]);
5220                 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]);
5221
5222                 // then the normals from the corners relative to origin
5223                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5224                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5225                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5226                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5227
5228                 // in a NORMAL view, forward cross left == up
5229                 // in a REFLECTED view, forward cross left == down
5230                 // so our cross products above need to be adjusted for a left handed coordinate system
5231                 CrossProduct(forward, left, v);
5232                 if(DotProduct(v, up) < 0)
5233                 {
5234                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5235                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5236                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5237                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5238                 }
5239
5240                 // Leaving those out was a mistake, those were in the old code, and they
5241                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5242                 // I couldn't reproduce it after adding those normalizations. --blub
5243                 VectorNormalize(r_refdef.view.frustum[0].normal);
5244                 VectorNormalize(r_refdef.view.frustum[1].normal);
5245                 VectorNormalize(r_refdef.view.frustum[2].normal);
5246                 VectorNormalize(r_refdef.view.frustum[3].normal);
5247
5248                 // make the corners absolute
5249                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5250                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5251                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5252                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5253
5254                 // one more normal
5255                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5256
5257                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5258                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5259                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5260                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5261                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5262         }
5263         else
5264         {
5265                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5266                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5267                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5268                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5269                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5270                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5271                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5272                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5273                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5274                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5275         }
5276         r_refdef.view.numfrustumplanes = 5;
5277
5278         if (r_refdef.view.useclipplane)
5279         {
5280                 r_refdef.view.numfrustumplanes = 6;
5281                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5282         }
5283
5284         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5285                 PlaneClassify(r_refdef.view.frustum + i);
5286
5287         // LordHavoc: note to all quake engine coders, Quake had a special case
5288         // for 90 degrees which assumed a square view (wrong), so I removed it,
5289         // Quake2 has it disabled as well.
5290
5291         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5292         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5293         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5294         //PlaneClassify(&frustum[0]);
5295
5296         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5297         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5298         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5299         //PlaneClassify(&frustum[1]);
5300
5301         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5302         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5303         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5304         //PlaneClassify(&frustum[2]);
5305
5306         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5307         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5308         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5309         //PlaneClassify(&frustum[3]);
5310
5311         // nearclip plane
5312         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5313         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5314         //PlaneClassify(&frustum[4]);
5315 }
5316
5317 void R_View_UpdateWithScissor(const int *myscissor)
5318 {
5319         R_Main_ResizeViewCache();
5320         R_View_SetFrustum(myscissor);
5321         R_View_WorldVisibility(r_refdef.view.useclipplane);
5322         R_View_UpdateEntityVisible();
5323         R_View_UpdateEntityLighting();
5324         R_AnimCache_CacheVisibleEntities();
5325 }
5326
5327 void R_View_Update(void)
5328 {
5329         R_Main_ResizeViewCache();
5330         R_View_SetFrustum(NULL);
5331         R_View_WorldVisibility(r_refdef.view.useclipplane);
5332         R_View_UpdateEntityVisible();
5333         R_View_UpdateEntityLighting();
5334         R_AnimCache_CacheVisibleEntities();
5335 }
5336
5337 float viewscalefpsadjusted = 1.0f;
5338
5339 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5340 {
5341         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5342         scale = bound(0.03125f, scale, 1.0f);
5343         *outwidth = (int)ceil(width * scale);
5344         *outheight = (int)ceil(height * scale);
5345 }
5346
5347 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5348 {
5349         const float *customclipplane = NULL;
5350         float plane[4];
5351         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5352         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5353         {
5354                 // LordHavoc: couldn't figure out how to make this approach the
5355                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5356                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5357                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5358                         dist = r_refdef.view.clipplane.dist;
5359                 plane[0] = r_refdef.view.clipplane.normal[0];
5360                 plane[1] = r_refdef.view.clipplane.normal[1];
5361                 plane[2] = r_refdef.view.clipplane.normal[2];
5362                 plane[3] = -dist;
5363                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5364         }
5365
5366         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5367         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5368
5369         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5370         if (!r_refdef.view.useperspective)
5371                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - 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);
5372         else if (vid.stencil && r_useinfinitefarclip.integer)
5373                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5374         else
5375                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5376         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5377         R_SetViewport(&r_refdef.view.viewport);
5378         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5379         {
5380                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5381                 float screenplane[4];
5382                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5383                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5384                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5385                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5386                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5387         }
5388 }
5389
5390 void R_EntityMatrix(const matrix4x4_t *matrix)
5391 {
5392         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5393         {
5394                 gl_modelmatrixchanged = false;
5395                 gl_modelmatrix = *matrix;
5396                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5397                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5398                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5399                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5400                 CHECKGLERROR
5401                 switch(vid.renderpath)
5402                 {
5403                 case RENDERPATH_D3D9:
5404 #ifdef SUPPORTD3D
5405                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5406                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5407 #endif
5408                         break;
5409                 case RENDERPATH_D3D10:
5410                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5411                         break;
5412                 case RENDERPATH_D3D11:
5413                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5414                         break;
5415                 case RENDERPATH_GL11:
5416                 case RENDERPATH_GL13:
5417                 case RENDERPATH_GLES1:
5418                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5419                         break;
5420                 case RENDERPATH_SOFT:
5421                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5422                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5423                         break;
5424                 case RENDERPATH_GL20:
5425                 case RENDERPATH_GLES2:
5426                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5427                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5428                         break;
5429                 }
5430         }
5431 }
5432
5433 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5434 {
5435         r_viewport_t viewport;
5436
5437         CHECKGLERROR
5438
5439         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5440         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, x2, y2, -10, 100, NULL);
5441         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5442         R_SetViewport(&viewport);
5443         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5444         GL_Color(1, 1, 1, 1);
5445         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5446         GL_BlendFunc(GL_ONE, GL_ZERO);
5447         GL_ScissorTest(false);
5448         GL_DepthMask(false);
5449         GL_DepthRange(0, 1);
5450         GL_DepthTest(false);
5451         GL_DepthFunc(GL_LEQUAL);
5452         R_EntityMatrix(&identitymatrix);
5453         R_Mesh_ResetTextureState();
5454         GL_PolygonOffset(0, 0);
5455         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5456         switch(vid.renderpath)
5457         {
5458         case RENDERPATH_GL11:
5459         case RENDERPATH_GL13:
5460         case RENDERPATH_GL20:
5461         case RENDERPATH_GLES1:
5462         case RENDERPATH_GLES2:
5463                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5464                 break;
5465         case RENDERPATH_D3D9:
5466         case RENDERPATH_D3D10:
5467         case RENDERPATH_D3D11:
5468         case RENDERPATH_SOFT:
5469                 break;
5470         }
5471         GL_CullFace(GL_NONE);
5472
5473         CHECKGLERROR
5474 }
5475
5476 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5477 {
5478         DrawQ_Finish();
5479
5480         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5481 }
5482
5483 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5484 {
5485         DrawQ_Finish();
5486
5487         R_SetupView(true, fbo, depthtexture, colortexture);
5488         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5489         GL_Color(1, 1, 1, 1);
5490         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5491         GL_BlendFunc(GL_ONE, GL_ZERO);
5492         GL_ScissorTest(true);
5493         GL_DepthMask(true);
5494         GL_DepthRange(0, 1);
5495         GL_DepthTest(true);
5496         GL_DepthFunc(GL_LEQUAL);
5497         R_EntityMatrix(&identitymatrix);
5498         R_Mesh_ResetTextureState();
5499         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5500         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5501         switch(vid.renderpath)
5502         {
5503         case RENDERPATH_GL11:
5504         case RENDERPATH_GL13:
5505         case RENDERPATH_GL20:
5506         case RENDERPATH_GLES1:
5507         case RENDERPATH_GLES2:
5508                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5509                 break;
5510         case RENDERPATH_D3D9:
5511         case RENDERPATH_D3D10:
5512         case RENDERPATH_D3D11:
5513         case RENDERPATH_SOFT:
5514                 break;
5515         }
5516         GL_CullFace(r_refdef.view.cullface_back);
5517 }
5518
5519 /*
5520 ================
5521 R_RenderView_UpdateViewVectors
5522 ================
5523 */
5524 void R_RenderView_UpdateViewVectors(void)
5525 {
5526         // break apart the view matrix into vectors for various purposes
5527         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5528         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5529         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5530         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5531         // make an inverted copy of the view matrix for tracking sprites
5532         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5533 }
5534
5535 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5536 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5537
5538 static void R_Water_StartFrame(void)
5539 {
5540         int i;
5541         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5542         r_waterstate_waterplane_t *p;
5543         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5544
5545         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5546                 return;
5547
5548         switch(vid.renderpath)
5549         {
5550         case RENDERPATH_GL20:
5551         case RENDERPATH_D3D9:
5552         case RENDERPATH_D3D10:
5553         case RENDERPATH_D3D11:
5554         case RENDERPATH_SOFT:
5555         case RENDERPATH_GLES2:
5556                 break;
5557         case RENDERPATH_GL11:
5558         case RENDERPATH_GL13:
5559         case RENDERPATH_GLES1:
5560                 return;
5561         }
5562
5563         // set waterwidth and waterheight to the water resolution that will be
5564         // used (often less than the screen resolution for faster rendering)
5565         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5566
5567         // calculate desired texture sizes
5568         // can't use water if the card does not support the texture size
5569         if (!r_water.integer || r_showsurfaces.integer)
5570                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5571         else if (vid.support.arb_texture_non_power_of_two)
5572         {
5573                 texturewidth = waterwidth;
5574                 textureheight = waterheight;
5575                 camerawidth = waterwidth;
5576                 cameraheight = waterheight;
5577         }
5578         else
5579         {
5580                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5581                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5582                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5583                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5584         }
5585
5586         // allocate textures as needed
5587         if (r_fb.water.texturewidth != texturewidth || r_fb.water.textureheight != textureheight || r_fb.water.camerawidth != camerawidth || r_fb.water.cameraheight != cameraheight || (r_fb.depthtexture && !usewaterfbo))
5588         {
5589                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5590                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5591                 {
5592                         if (p->texture_refraction)
5593                                 R_FreeTexture(p->texture_refraction);
5594                         p->texture_refraction = NULL;
5595                         if (p->fbo_refraction)
5596                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5597                         p->fbo_refraction = 0;
5598                         if (p->texture_reflection)
5599                                 R_FreeTexture(p->texture_reflection);
5600                         p->texture_reflection = NULL;
5601                         if (p->fbo_reflection)
5602                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5603                         p->fbo_reflection = 0;
5604                         if (p->texture_camera)
5605                                 R_FreeTexture(p->texture_camera);
5606                         p->texture_camera = NULL;
5607                         if (p->fbo_camera)
5608                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5609                         p->fbo_camera = 0;
5610                 }
5611                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5612                 r_fb.water.texturewidth = texturewidth;
5613                 r_fb.water.textureheight = textureheight;
5614                 r_fb.water.camerawidth = camerawidth;
5615                 r_fb.water.cameraheight = cameraheight;
5616         }
5617
5618         if (r_fb.water.texturewidth)
5619         {
5620                 int scaledwidth, scaledheight;
5621
5622                 r_fb.water.enabled = true;
5623
5624                 // water resolution is usually reduced
5625                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5626                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5627                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5628
5629                 // set up variables that will be used in shader setup
5630                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5631                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5632                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5633                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5634         }
5635
5636         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5637         r_fb.water.numwaterplanes = 0;
5638 }
5639
5640 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5641 {
5642         int planeindex, bestplaneindex, vertexindex;
5643         vec3_t mins, maxs, normal, center, v, n;
5644         vec_t planescore, bestplanescore;
5645         mplane_t plane;
5646         r_waterstate_waterplane_t *p;
5647         texture_t *t = R_GetCurrentTexture(surface->texture);
5648
5649         rsurface.texture = t;
5650         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5651         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5652         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5653                 return;
5654         // average the vertex normals, find the surface bounds (after deformvertexes)
5655         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5656         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5657         VectorCopy(n, normal);
5658         VectorCopy(v, mins);
5659         VectorCopy(v, maxs);
5660         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5661         {
5662                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5663                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5664                 VectorAdd(normal, n, normal);
5665                 mins[0] = min(mins[0], v[0]);
5666                 mins[1] = min(mins[1], v[1]);
5667                 mins[2] = min(mins[2], v[2]);
5668                 maxs[0] = max(maxs[0], v[0]);
5669                 maxs[1] = max(maxs[1], v[1]);
5670                 maxs[2] = max(maxs[2], v[2]);
5671         }
5672         VectorNormalize(normal);
5673         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5674
5675         VectorCopy(normal, plane.normal);
5676         VectorNormalize(plane.normal);
5677         plane.dist = DotProduct(center, plane.normal);
5678         PlaneClassify(&plane);
5679         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5680         {
5681                 // skip backfaces (except if nocullface is set)
5682 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5683 //                      return;
5684                 VectorNegate(plane.normal, plane.normal);
5685                 plane.dist *= -1;
5686                 PlaneClassify(&plane);
5687         }
5688
5689
5690         // find a matching plane if there is one
5691         bestplaneindex = -1;
5692         bestplanescore = 1048576.0f;
5693         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5694         {
5695                 if(p->camera_entity == t->camera_entity)
5696                 {
5697                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5698                         if (bestplaneindex < 0 || bestplanescore > planescore)
5699                         {
5700                                 bestplaneindex = planeindex;
5701                                 bestplanescore = planescore;
5702                         }
5703                 }
5704         }
5705         planeindex = bestplaneindex;
5706         p = r_fb.water.waterplanes + planeindex;
5707
5708         // if this surface does not fit any known plane rendered this frame, add one
5709         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5710         {
5711                 // store the new plane
5712                 planeindex = r_fb.water.numwaterplanes++;
5713                 p = r_fb.water.waterplanes + planeindex;
5714                 p->plane = plane;
5715                 // clear materialflags and pvs
5716                 p->materialflags = 0;
5717                 p->pvsvalid = false;
5718                 p->camera_entity = t->camera_entity;
5719                 VectorCopy(mins, p->mins);
5720                 VectorCopy(maxs, p->maxs);
5721         }
5722         else
5723         {
5724                 // merge mins/maxs when we're adding this surface to the plane
5725                 p->mins[0] = min(p->mins[0], mins[0]);
5726                 p->mins[1] = min(p->mins[1], mins[1]);
5727                 p->mins[2] = min(p->mins[2], mins[2]);
5728                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5729                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5730                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5731         }
5732         // merge this surface's materialflags into the waterplane
5733         p->materialflags |= t->currentmaterialflags;
5734         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5735         {
5736                 // merge this surface's PVS into the waterplane
5737                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5738                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5739                 {
5740                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5741                         p->pvsvalid = true;
5742                 }
5743         }
5744 }
5745
5746 extern cvar_t r_drawparticles;
5747 extern cvar_t r_drawdecals;
5748
5749 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5750 {
5751         int myscissor[4];
5752         r_refdef_view_t originalview;
5753         r_refdef_view_t myview;
5754         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;
5755         r_waterstate_waterplane_t *p;
5756         vec3_t visorigin;
5757         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5758
5759         originalview = r_refdef.view;
5760
5761         // lowquality hack, temporarily shut down some cvars and restore afterwards
5762         qualityreduction = r_water_lowquality.integer;
5763         if (qualityreduction > 0)
5764         {
5765                 if (qualityreduction >= 1)
5766                 {
5767                         old_r_shadows = r_shadows.integer;
5768                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5769                         old_r_dlight = r_shadow_realtime_dlight.integer;
5770                         Cvar_SetValueQuick(&r_shadows, 0);
5771                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5772                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5773                 }
5774                 if (qualityreduction >= 2)
5775                 {
5776                         old_r_dynamic = r_dynamic.integer;
5777                         old_r_particles = r_drawparticles.integer;
5778                         old_r_decals = r_drawdecals.integer;
5779                         Cvar_SetValueQuick(&r_dynamic, 0);
5780                         Cvar_SetValueQuick(&r_drawparticles, 0);
5781                         Cvar_SetValueQuick(&r_drawdecals, 0);
5782                 }
5783         }
5784
5785         // make sure enough textures are allocated
5786         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5787         {
5788                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5789                 {
5790                         if (!p->texture_refraction)
5791                                 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);
5792                         if (!p->texture_refraction)
5793                                 goto error;
5794                         if (usewaterfbo)
5795                         {
5796                                 if (r_fb.water.depthtexture == NULL)
5797                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5798                                 if (p->fbo_refraction == 0)
5799                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5800                         }
5801                 }
5802                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5803                 {
5804                         if (!p->texture_camera)
5805                                 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);
5806                         if (!p->texture_camera)
5807                                 goto error;
5808                         if (usewaterfbo)
5809                         {
5810                                 if (r_fb.water.depthtexture == NULL)
5811                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5812                                 if (p->fbo_camera == 0)
5813                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5814                         }
5815                 }
5816
5817                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5818                 {
5819                         if (!p->texture_reflection)
5820                                 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);
5821                         if (!p->texture_reflection)
5822                                 goto error;
5823                         if (usewaterfbo)
5824                         {
5825                                 if (r_fb.water.depthtexture == NULL)
5826                                         r_fb.water.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, 24, false, vid.support.ext_packed_depth_stencil);
5827                                 if (p->fbo_reflection == 0)
5828                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5829                         }
5830                 }
5831         }
5832
5833         // render views
5834         r_refdef.view = originalview;
5835         r_refdef.view.showdebug = false;
5836         r_refdef.view.width = r_fb.water.waterwidth;
5837         r_refdef.view.height = r_fb.water.waterheight;
5838         r_refdef.view.useclipplane = true;
5839         myview = r_refdef.view;
5840         r_fb.water.renderingscene = true;
5841         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5842         {
5843                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5844                 {
5845                         r_refdef.view = myview;
5846                         if(r_water_scissormode.integer)
5847                         {
5848                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5849                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5850                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5851                         }
5852
5853                         // render reflected scene and copy into texture
5854                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5855                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5856                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5857                         r_refdef.view.clipplane = p->plane;
5858                         // reverse the cullface settings for this render
5859                         r_refdef.view.cullface_front = GL_FRONT;
5860                         r_refdef.view.cullface_back = GL_BACK;
5861                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5862                         {
5863                                 r_refdef.view.usecustompvs = true;
5864                                 if (p->pvsvalid)
5865                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5866                                 else
5867                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5868                         }
5869
5870                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5871                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5872                         R_ClearScreen(r_refdef.fogenabled);
5873                         if(r_water_scissormode.integer & 2)
5874                                 R_View_UpdateWithScissor(myscissor);
5875                         else
5876                                 R_View_Update();
5877                         if(r_water_scissormode.integer & 1)
5878                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5879                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5880
5881                         if (!p->fbo_reflection)
5882                                 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);
5883                         r_fb.water.hideplayer = false;
5884                 }
5885
5886                 // render the normal view scene and copy into texture
5887                 // (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)
5888                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5889                 {
5890                         r_refdef.view = myview;
5891                         if(r_water_scissormode.integer)
5892                         {
5893                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5894                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5895                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5896                         }
5897
5898                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5899
5900                         r_refdef.view.clipplane = p->plane;
5901                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5902                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5903
5904                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5905                         {
5906                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5907                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5908                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5909                                 R_RenderView_UpdateViewVectors();
5910                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5911                                 {
5912                                         r_refdef.view.usecustompvs = true;
5913                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5914                                 }
5915                         }
5916
5917                         PlaneClassify(&r_refdef.view.clipplane);
5918
5919                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5920                         R_ClearScreen(r_refdef.fogenabled);
5921                         if(r_water_scissormode.integer & 2)
5922                                 R_View_UpdateWithScissor(myscissor);
5923                         else
5924                                 R_View_Update();
5925                         if(r_water_scissormode.integer & 1)
5926                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5927                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5928
5929                         if (!p->fbo_refraction)
5930                                 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);
5931                         r_fb.water.hideplayer = false;
5932                 }
5933                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5934                 {
5935                         r_refdef.view = myview;
5936
5937                         r_refdef.view.clipplane = p->plane;
5938                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5939                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5940
5941                         r_refdef.view.width = r_fb.water.camerawidth;
5942                         r_refdef.view.height = r_fb.water.cameraheight;
5943                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5944                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5945                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5946                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5947
5948                         if(p->camera_entity)
5949                         {
5950                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5951                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5952                         }
5953
5954                         // note: all of the view is used for displaying... so
5955                         // there is no use in scissoring
5956
5957                         // reverse the cullface settings for this render
5958                         r_refdef.view.cullface_front = GL_FRONT;
5959                         r_refdef.view.cullface_back = GL_BACK;
5960                         // also reverse the view matrix
5961                         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
5962                         R_RenderView_UpdateViewVectors();
5963                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5964                         {
5965                                 r_refdef.view.usecustompvs = true;
5966                                 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);
5967                         }
5968                         
5969                         // camera needs no clipplane
5970                         r_refdef.view.useclipplane = false;
5971
5972                         PlaneClassify(&r_refdef.view.clipplane);
5973
5974                         r_fb.water.hideplayer = false;
5975
5976                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5977                         R_ClearScreen(r_refdef.fogenabled);
5978                         R_View_Update();
5979                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5980
5981                         if (!p->fbo_camera)
5982                                 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);
5983                         r_fb.water.hideplayer = false;
5984                 }
5985
5986         }
5987         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5988         r_fb.water.renderingscene = false;
5989         r_refdef.view = originalview;
5990         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5991         if (!r_fb.water.depthtexture)
5992                 R_ClearScreen(r_refdef.fogenabled);
5993         R_View_Update();
5994         goto finish;
5995 error:
5996         r_refdef.view = originalview;
5997         r_fb.water.renderingscene = false;
5998         Cvar_SetValueQuick(&r_water, 0);
5999         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6000 finish:
6001         // lowquality hack, restore cvars
6002         if (qualityreduction > 0)
6003         {
6004                 if (qualityreduction >= 1)
6005                 {
6006                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6007                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6008                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6009                 }
6010                 if (qualityreduction >= 2)
6011                 {
6012                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6013                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6014                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6015                 }
6016         }
6017 }
6018
6019 void R_Bloom_StartFrame(void)
6020 {
6021         int i;
6022         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6023         int viewwidth, viewheight;
6024         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6025         textype_t textype = TEXTYPE_COLORBUFFER;
6026
6027         switch (vid.renderpath)
6028         {
6029         case RENDERPATH_GL20:
6030         case RENDERPATH_GLES2:
6031                 if (vid.support.ext_framebuffer_object)
6032                 {
6033                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6034                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6035                 }
6036                 break;
6037         case RENDERPATH_GL11:
6038         case RENDERPATH_GL13:
6039         case RENDERPATH_GLES1:
6040         case RENDERPATH_D3D9:
6041         case RENDERPATH_D3D10:
6042         case RENDERPATH_D3D11:
6043         case RENDERPATH_SOFT:
6044                 break;
6045         }
6046
6047         if (r_viewscale_fpsscaling.integer)
6048         {
6049                 double actualframetime;
6050                 double targetframetime;
6051                 double adjust;
6052                 actualframetime = r_refdef.lastdrawscreentime;
6053                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6054                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6055                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6056                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6057                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6058                 viewscalefpsadjusted += adjust;
6059                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6060         }
6061         else
6062                 viewscalefpsadjusted = 1.0f;
6063
6064         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6065
6066         switch(vid.renderpath)
6067         {
6068         case RENDERPATH_GL20:
6069         case RENDERPATH_D3D9:
6070         case RENDERPATH_D3D10:
6071         case RENDERPATH_D3D11:
6072         case RENDERPATH_SOFT:
6073         case RENDERPATH_GLES2:
6074                 break;
6075         case RENDERPATH_GL11:
6076         case RENDERPATH_GL13:
6077         case RENDERPATH_GLES1:
6078                 return;
6079         }
6080
6081         // set bloomwidth and bloomheight to the bloom resolution that will be
6082         // used (often less than the screen resolution for faster rendering)
6083         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6084         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6085         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6086         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6087         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6088
6089         // calculate desired texture sizes
6090         if (vid.support.arb_texture_non_power_of_two)
6091         {
6092                 screentexturewidth = vid.width;
6093                 screentextureheight = vid.height;
6094                 bloomtexturewidth = r_fb.bloomwidth;
6095                 bloomtextureheight = r_fb.bloomheight;
6096         }
6097         else
6098         {
6099                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6100                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6101                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6102                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6103         }
6104
6105         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))
6106         {
6107                 Cvar_SetValueQuick(&r_bloom, 0);
6108                 Cvar_SetValueQuick(&r_motionblur, 0);
6109                 Cvar_SetValueQuick(&r_damageblur, 0);
6110         }
6111
6112         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6113          && !r_bloom.integer
6114          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6115          && !useviewfbo
6116          && r_viewscale.value == 1.0f
6117          && !r_viewscale_fpsscaling.integer)
6118                 screentexturewidth = screentextureheight = 0;
6119         if (!r_bloom.integer)
6120                 bloomtexturewidth = bloomtextureheight = 0;
6121
6122         // allocate textures as needed
6123         if (r_fb.screentexturewidth != screentexturewidth
6124          || r_fb.screentextureheight != screentextureheight
6125          || r_fb.bloomtexturewidth != bloomtexturewidth
6126          || r_fb.bloomtextureheight != bloomtextureheight
6127          || r_fb.textype != textype
6128          || useviewfbo != (r_fb.fbo != 0))
6129         {
6130                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6131                 {
6132                         if (r_fb.bloomtexture[i])
6133                                 R_FreeTexture(r_fb.bloomtexture[i]);
6134                         r_fb.bloomtexture[i] = NULL;
6135
6136                         if (r_fb.bloomfbo[i])
6137                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6138                         r_fb.bloomfbo[i] = 0;
6139                 }
6140
6141                 if (r_fb.fbo)
6142                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6143                 r_fb.fbo = 0;
6144
6145                 if (r_fb.colortexture)
6146                         R_FreeTexture(r_fb.colortexture);
6147                 r_fb.colortexture = NULL;
6148
6149                 if (r_fb.depthtexture)
6150                         R_FreeTexture(r_fb.depthtexture);
6151                 r_fb.depthtexture = NULL;
6152
6153                 if (r_fb.ghosttexture)
6154                         R_FreeTexture(r_fb.ghosttexture);
6155                 r_fb.ghosttexture = NULL;
6156
6157                 r_fb.screentexturewidth = screentexturewidth;
6158                 r_fb.screentextureheight = screentextureheight;
6159                 r_fb.bloomtexturewidth = bloomtexturewidth;
6160                 r_fb.bloomtextureheight = bloomtextureheight;
6161                 r_fb.textype = textype;
6162
6163                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6164                 {
6165                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6166                                 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);
6167                         r_fb.ghosttexture_valid = false;
6168                         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);
6169                         if (useviewfbo)
6170                         {
6171                                 // FIXME: choose depth bits based on a cvar
6172                                 r_fb.depthtexture = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, 24, false, vid.support.ext_packed_depth_stencil);
6173                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6174                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6175 #ifndef USE_GLES2
6176                                 // render depth into one texture and color into the other
6177                                 if (qglDrawBuffer)
6178                                 {
6179                                         int status;
6180                                         qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6181                                         qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6182                                         status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6183                                         if (status != GL_FRAMEBUFFER_COMPLETE)
6184                                                 Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6185                                 }
6186 #endif
6187                         }
6188                 }
6189
6190                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6191                 {
6192                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6193                         {
6194                                 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);
6195                                 if (useviewfbo)
6196                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6197                         }
6198                 }
6199         }
6200
6201         // bloom texture is a different resolution
6202         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6203         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6204         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6205         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6206         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6207
6208         // set up a texcoord array for the full resolution screen image
6209         // (we have to keep this around to copy back during final render)
6210         r_fb.screentexcoord2f[0] = 0;
6211         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6212         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6213         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6214         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6215         r_fb.screentexcoord2f[5] = 0;
6216         r_fb.screentexcoord2f[6] = 0;
6217         r_fb.screentexcoord2f[7] = 0;
6218
6219         // set up a texcoord array for the reduced resolution bloom image
6220         // (which will be additive blended over the screen image)
6221         r_fb.bloomtexcoord2f[0] = 0;
6222         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6223         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6224         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6225         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6226         r_fb.bloomtexcoord2f[5] = 0;
6227         r_fb.bloomtexcoord2f[6] = 0;
6228         r_fb.bloomtexcoord2f[7] = 0;
6229
6230         switch(vid.renderpath)
6231         {
6232         case RENDERPATH_GL11:
6233         case RENDERPATH_GL13:
6234         case RENDERPATH_GL20:
6235         case RENDERPATH_SOFT:
6236         case RENDERPATH_GLES1:
6237         case RENDERPATH_GLES2:
6238                 break;
6239         case RENDERPATH_D3D9:
6240         case RENDERPATH_D3D10:
6241         case RENDERPATH_D3D11:
6242                 {
6243                         int i;
6244                         for (i = 0;i < 4;i++)
6245                         {
6246                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6247                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6248                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6249                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6250                         }
6251                 }
6252                 break;
6253         }
6254
6255         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);
6256
6257         if (r_fb.fbo)
6258                 r_refdef.view.clear = true;
6259 }
6260
6261 void R_Bloom_MakeTexture(void)
6262 {
6263         int x, range, dir;
6264         float xoffset, yoffset, r, brighten;
6265         rtexture_t *intex;
6266         float colorscale = r_bloom_colorscale.value;
6267
6268         r_refdef.stats.bloom++;
6269
6270         if (!r_fb.fbo)
6271         {
6272                 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);
6273                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6274         }
6275
6276         // scale down screen texture to the bloom texture size
6277         CHECKGLERROR
6278         r_fb.bloomindex = 0;
6279         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6280         R_SetViewport(&r_fb.bloomviewport);
6281         GL_BlendFunc(GL_ONE, GL_ZERO);
6282         GL_Color(colorscale, colorscale, colorscale, 1);
6283         // 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...
6284         switch(vid.renderpath)
6285         {
6286         case RENDERPATH_GL11:
6287         case RENDERPATH_GL13:
6288         case RENDERPATH_GL20:
6289         case RENDERPATH_GLES1:
6290         case RENDERPATH_GLES2:
6291         case RENDERPATH_SOFT:
6292                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6293                 break;
6294         case RENDERPATH_D3D9:
6295         case RENDERPATH_D3D10:
6296         case RENDERPATH_D3D11:
6297                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6298                 break;
6299         }
6300         // TODO: do boxfilter scale-down in shader?
6301         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6302         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6303         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6304
6305         // we now have a properly scaled bloom image
6306         if (!r_fb.bloomfbo[r_fb.bloomindex])
6307         {
6308                 // copy it into the bloom texture
6309                 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);
6310                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6311         }
6312
6313         // multiply bloom image by itself as many times as desired
6314         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6315         {
6316                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6317                 r_fb.bloomindex ^= 1;
6318                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6319                 x *= 2;
6320                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6321                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6322                 GL_Color(r,r,r,1);
6323                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6324                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6325                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6326                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6327
6328                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6329                 {
6330                         // copy the darkened image to a texture
6331                         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);
6332                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6333                 }
6334         }
6335
6336         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6337         brighten = r_bloom_brighten.value;
6338         brighten = sqrt(brighten);
6339         if(range >= 1)
6340                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6341
6342         for (dir = 0;dir < 2;dir++)
6343         {
6344                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6345                 r_fb.bloomindex ^= 1;
6346                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6347                 // blend on at multiple vertical offsets to achieve a vertical blur
6348                 // TODO: do offset blends using GLSL
6349                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6350                 GL_BlendFunc(GL_ONE, GL_ZERO);
6351                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6352                 for (x = -range;x <= range;x++)
6353                 {
6354                         if (!dir){xoffset = 0;yoffset = x;}
6355                         else {xoffset = x;yoffset = 0;}
6356                         xoffset /= (float)r_fb.bloomtexturewidth;
6357                         yoffset /= (float)r_fb.bloomtextureheight;
6358                         // compute a texcoord array with the specified x and y offset
6359                         r_fb.offsettexcoord2f[0] = xoffset+0;
6360                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6361                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6362                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6363                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6364                         r_fb.offsettexcoord2f[5] = yoffset+0;
6365                         r_fb.offsettexcoord2f[6] = xoffset+0;
6366                         r_fb.offsettexcoord2f[7] = yoffset+0;
6367                         // this r value looks like a 'dot' particle, fading sharply to
6368                         // black at the edges
6369                         // (probably not realistic but looks good enough)
6370                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6371                         //r = brighten/(range*2+1);
6372                         r = brighten / (range * 2 + 1);
6373                         if(range >= 1)
6374                                 r *= (1 - x*x/(float)(range*range));
6375                         GL_Color(r, r, r, 1);
6376                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6377                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6378                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6379                         GL_BlendFunc(GL_ONE, GL_ONE);
6380                 }
6381
6382                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6383                 {
6384                         // copy the vertically or horizontally blurred bloom view to a texture
6385                         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);
6386                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6387                 }
6388         }
6389 }
6390
6391 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6392 {
6393         unsigned int permutation;
6394         float uservecs[4][4];
6395
6396         switch (vid.renderpath)
6397         {
6398         case RENDERPATH_GL20:
6399         case RENDERPATH_D3D9:
6400         case RENDERPATH_D3D10:
6401         case RENDERPATH_D3D11:
6402         case RENDERPATH_SOFT:
6403         case RENDERPATH_GLES2:
6404                 permutation =
6405                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6406                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6407                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6408                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6409                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6410
6411                 if (r_fb.colortexture)
6412                 {
6413                         if (!r_fb.fbo)
6414                         {
6415                                 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);
6416                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6417                         }
6418
6419                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6420                         {
6421                                 // declare variables
6422                                 float blur_factor, blur_mouseaccel, blur_velocity;
6423                                 static float blur_average; 
6424                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6425
6426                                 // set a goal for the factoring
6427                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6428                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6429                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6430                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6431                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6432                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6433
6434                                 // from the goal, pick an averaged value between goal and last value
6435                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6436                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6437
6438                                 // enforce minimum amount of blur 
6439                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6440
6441                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6442
6443                                 // calculate values into a standard alpha
6444                                 cl.motionbluralpha = 1 - exp(-
6445                                                 (
6446                                                  (r_motionblur.value * blur_factor / 80)
6447                                                  +
6448                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6449                                                 )
6450                                                 /
6451                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6452                                           );
6453
6454                                 // randomization for the blur value to combat persistent ghosting
6455                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6456                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6457
6458                                 // apply the blur
6459                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6460                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6461                                 {
6462                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6463                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6464                                         switch(vid.renderpath)
6465                                         {
6466                                         case RENDERPATH_GL11:
6467                                         case RENDERPATH_GL13:
6468                                         case RENDERPATH_GL20:
6469                                         case RENDERPATH_GLES1:
6470                                         case RENDERPATH_GLES2:
6471                                         case RENDERPATH_SOFT:
6472                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6473                                                 break;
6474                                         case RENDERPATH_D3D9:
6475                                         case RENDERPATH_D3D10:
6476                                         case RENDERPATH_D3D11:
6477                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6478                                                 break;
6479                                         }
6480                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6481                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6482                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6483                                 }
6484
6485                                 // updates old view angles for next pass
6486                                 VectorCopy(cl.viewangles, blur_oldangles);
6487
6488                                 // copy view into the ghost texture
6489                                 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);
6490                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6491                                 r_fb.ghosttexture_valid = true;
6492                         }
6493                 }
6494                 else
6495                 {
6496                         // no r_fb.colortexture means we're rendering to the real fb
6497                         // we may still have to do view tint...
6498                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6499                         {
6500                                 // apply a color tint to the whole view
6501                                 R_ResetViewRendering2D(0, NULL, NULL);
6502                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6503                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6504                                 R_SetupShader_Generic_NoTexture(false, true);
6505                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6506                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6507                         }
6508                         break; // no screen processing, no bloom, skip it
6509                 }
6510
6511                 if (r_fb.bloomtexture[0])
6512                 {
6513                         // make the bloom texture
6514                         R_Bloom_MakeTexture();
6515                 }
6516
6517 #if _MSC_VER >= 1400
6518 #define sscanf sscanf_s
6519 #endif
6520                 memset(uservecs, 0, sizeof(uservecs));
6521                 if (r_glsl_postprocess_uservec1_enable.integer)
6522                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6523                 if (r_glsl_postprocess_uservec2_enable.integer)
6524                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6525                 if (r_glsl_postprocess_uservec3_enable.integer)
6526                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6527                 if (r_glsl_postprocess_uservec4_enable.integer)
6528                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6529
6530                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6531                 GL_Color(1, 1, 1, 1);
6532                 GL_BlendFunc(GL_ONE, GL_ZERO);
6533
6534                 switch(vid.renderpath)
6535                 {
6536                 case RENDERPATH_GL20:
6537                 case RENDERPATH_GLES2:
6538                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6539                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6540                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6541                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6542                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6543                         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]);
6544                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6545                         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]);
6546                         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]);
6547                         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]);
6548                         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]);
6549                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6550                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6551                         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);
6552                         break;
6553                 case RENDERPATH_D3D9:
6554 #ifdef SUPPORTD3D
6555                         // 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...
6556                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6557                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6558                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6559                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6560                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6561                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6562                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6563                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6564                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6565                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6566                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6567                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6568                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6569                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6570 #endif
6571                         break;
6572                 case RENDERPATH_D3D10:
6573                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6574                         break;
6575                 case RENDERPATH_D3D11:
6576                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6577                         break;
6578                 case RENDERPATH_SOFT:
6579                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6580                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6581                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6582                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6583                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6584                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6585                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6586                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6587                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6588                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6589                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6590                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6591                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6592                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6593                         break;
6594                 default:
6595                         break;
6596                 }
6597                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6598                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6599                 break;
6600         case RENDERPATH_GL11:
6601         case RENDERPATH_GL13:
6602         case RENDERPATH_GLES1:
6603                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6604                 {
6605                         // apply a color tint to the whole view
6606                         R_ResetViewRendering2D(0, NULL, NULL);
6607                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6608                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6609                         R_SetupShader_Generic_NoTexture(false, true);
6610                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6611                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6612                 }
6613                 break;
6614         }
6615 }
6616
6617 matrix4x4_t r_waterscrollmatrix;
6618
6619 void R_UpdateFog(void)
6620 {
6621         // Nehahra fog
6622         if (gamemode == GAME_NEHAHRA)
6623         {
6624                 if (gl_fogenable.integer)
6625                 {
6626                         r_refdef.oldgl_fogenable = true;
6627                         r_refdef.fog_density = gl_fogdensity.value;
6628                         r_refdef.fog_red = gl_fogred.value;
6629                         r_refdef.fog_green = gl_foggreen.value;
6630                         r_refdef.fog_blue = gl_fogblue.value;
6631                         r_refdef.fog_alpha = 1;
6632                         r_refdef.fog_start = 0;
6633                         r_refdef.fog_end = gl_skyclip.value;
6634                         r_refdef.fog_height = 1<<30;
6635                         r_refdef.fog_fadedepth = 128;
6636                 }
6637                 else if (r_refdef.oldgl_fogenable)
6638                 {
6639                         r_refdef.oldgl_fogenable = false;
6640                         r_refdef.fog_density = 0;
6641                         r_refdef.fog_red = 0;
6642                         r_refdef.fog_green = 0;
6643                         r_refdef.fog_blue = 0;
6644                         r_refdef.fog_alpha = 0;
6645                         r_refdef.fog_start = 0;
6646                         r_refdef.fog_end = 0;
6647                         r_refdef.fog_height = 1<<30;
6648                         r_refdef.fog_fadedepth = 128;
6649                 }
6650         }
6651
6652         // fog parms
6653         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6654         r_refdef.fog_start = max(0, r_refdef.fog_start);
6655         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6656
6657         if (r_refdef.fog_density && r_drawfog.integer)
6658         {
6659                 r_refdef.fogenabled = true;
6660                 // this is the point where the fog reaches 0.9986 alpha, which we
6661                 // consider a good enough cutoff point for the texture
6662                 // (0.9986 * 256 == 255.6)
6663                 if (r_fog_exp2.integer)
6664                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6665                 else
6666                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6667                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6668                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6669                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6670                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6671                         R_BuildFogHeightTexture();
6672                 // fog color was already set
6673                 // update the fog texture
6674                 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)
6675                         R_BuildFogTexture();
6676                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6677                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6678         }
6679         else
6680                 r_refdef.fogenabled = false;
6681
6682         // fog color
6683         if (r_refdef.fog_density)
6684         {
6685                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6686                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6687                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6688
6689                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6690                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6691                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6692                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6693
6694                 {
6695                         vec3_t fogvec;
6696                         VectorCopy(r_refdef.fogcolor, fogvec);
6697                         //   color.rgb *= ContrastBoost * SceneBrightness;
6698                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6699                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6700                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6701                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6702                 }
6703         }
6704 }
6705
6706 void R_UpdateVariables(void)
6707 {
6708         R_Textures_Frame();
6709
6710         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6711
6712         r_refdef.farclip = r_farclip_base.value;
6713         if (r_refdef.scene.worldmodel)
6714                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6715         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6716
6717         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6718                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6719         r_refdef.polygonfactor = 0;
6720         r_refdef.polygonoffset = 0;
6721         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6722         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6723
6724         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6725         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6726         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6727         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6728         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6729         if (FAKELIGHT_ENABLED)
6730         {
6731                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6732         }
6733         if (r_showsurfaces.integer)
6734         {
6735                 r_refdef.scene.rtworld = false;
6736                 r_refdef.scene.rtworldshadows = false;
6737                 r_refdef.scene.rtdlight = false;
6738                 r_refdef.scene.rtdlightshadows = false;
6739                 r_refdef.lightmapintensity = 0;
6740         }
6741
6742         switch(vid.renderpath)
6743         {
6744         case RENDERPATH_GL20:
6745         case RENDERPATH_D3D9:
6746         case RENDERPATH_D3D10:
6747         case RENDERPATH_D3D11:
6748         case RENDERPATH_SOFT:
6749         case RENDERPATH_GLES2:
6750                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6751                 {
6752                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6753                         {
6754                                 // build GLSL gamma texture
6755 #define RAMPWIDTH 256
6756                                 unsigned short ramp[RAMPWIDTH * 3];
6757                                 unsigned char rampbgr[RAMPWIDTH][4];
6758                                 int i;
6759
6760                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6761
6762                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6763                                 for(i = 0; i < RAMPWIDTH; ++i)
6764                                 {
6765                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6766                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6767                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6768                                         rampbgr[i][3] = 0;
6769                                 }
6770                                 if (r_texture_gammaramps)
6771                                 {
6772                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6773                                 }
6774                                 else
6775                                 {
6776                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6777                                 }
6778                         }
6779                 }
6780                 else
6781                 {
6782                         // remove GLSL gamma texture
6783                 }
6784                 break;
6785         case RENDERPATH_GL11:
6786         case RENDERPATH_GL13:
6787         case RENDERPATH_GLES1:
6788                 break;
6789         }
6790 }
6791
6792 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6793 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6794 /*
6795 ================
6796 R_SelectScene
6797 ================
6798 */
6799 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6800         if( scenetype != r_currentscenetype ) {
6801                 // store the old scenetype
6802                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6803                 r_currentscenetype = scenetype;
6804                 // move in the new scene
6805                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6806         }
6807 }
6808
6809 /*
6810 ================
6811 R_GetScenePointer
6812 ================
6813 */
6814 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6815 {
6816         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6817         if( scenetype == r_currentscenetype ) {
6818                 return &r_refdef.scene;
6819         } else {
6820                 return &r_scenes_store[ scenetype ];
6821         }
6822 }
6823
6824 int R_SortEntities_Compare(const void *ap, const void *bp)
6825 {
6826         const entity_render_t *a = *(const entity_render_t **)ap;
6827         const entity_render_t *b = *(const entity_render_t **)bp;
6828
6829         // 1. compare model
6830         if(a->model < b->model)
6831                 return -1;
6832         if(a->model > b->model)
6833                 return +1;
6834
6835         // 2. compare skin
6836         // TODO possibly calculate the REAL skinnum here first using
6837         // skinscenes?
6838         if(a->skinnum < b->skinnum)
6839                 return -1;
6840         if(a->skinnum > b->skinnum)
6841                 return +1;
6842
6843         // everything we compared is equal
6844         return 0;
6845 }
6846 void R_SortEntities(void)
6847 {
6848         // below or equal 2 ents, sorting never gains anything
6849         if(r_refdef.scene.numentities <= 2)
6850                 return;
6851         // sort
6852         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6853 }
6854
6855 /*
6856 ================
6857 R_RenderView
6858 ================
6859 */
6860 int dpsoftrast_test;
6861 extern void R_Shadow_UpdateBounceGridTexture(void);
6862 extern cvar_t r_shadow_bouncegrid;
6863 void R_RenderView(void)
6864 {
6865         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6866         int fbo;
6867         rtexture_t *depthtexture;
6868         rtexture_t *colortexture;
6869
6870         dpsoftrast_test = r_test.integer;
6871
6872         if (r_timereport_active)
6873                 R_TimeReport("start");
6874         r_textureframe++; // used only by R_GetCurrentTexture
6875         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6876
6877         if(R_CompileShader_CheckStaticParms())
6878                 R_GLSL_Restart_f();
6879
6880         if (!r_drawentities.integer)
6881                 r_refdef.scene.numentities = 0;
6882         else if (r_sortentities.integer)
6883                 R_SortEntities();
6884
6885         R_AnimCache_ClearCache();
6886         R_FrameData_NewFrame();
6887
6888         /* adjust for stereo display */
6889         if(R_Stereo_Active())
6890         {
6891                 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);
6892                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6893         }
6894
6895         if (r_refdef.view.isoverlay)
6896         {
6897                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6898                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6899                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6900                 R_TimeReport("depthclear");
6901
6902                 r_refdef.view.showdebug = false;
6903
6904                 r_fb.water.enabled = false;
6905                 r_fb.water.numwaterplanes = 0;
6906
6907                 R_RenderScene(0, NULL, NULL);
6908
6909                 r_refdef.view.matrix = originalmatrix;
6910
6911                 CHECKGLERROR
6912                 return;
6913         }
6914
6915         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6916         {
6917                 r_refdef.view.matrix = originalmatrix;
6918                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6919         }
6920
6921         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6922
6923         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6924                 // in sRGB fallback, behave similar to true sRGB: convert this
6925                 // value from linear to sRGB
6926                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6927
6928         R_RenderView_UpdateViewVectors();
6929
6930         R_Shadow_UpdateWorldLightSelection();
6931
6932         R_Bloom_StartFrame();
6933         R_Water_StartFrame();
6934
6935         // now we probably have an fbo to render into
6936         fbo = r_fb.fbo;
6937         depthtexture = r_fb.depthtexture;
6938         colortexture = r_fb.colortexture;
6939
6940         CHECKGLERROR
6941         if (r_timereport_active)
6942                 R_TimeReport("viewsetup");
6943
6944         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6945
6946         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6947         {
6948                 R_ClearScreen(r_refdef.fogenabled);
6949                 if (r_timereport_active)
6950                         R_TimeReport("viewclear");
6951         }
6952         r_refdef.view.clear = true;
6953
6954         r_refdef.view.showdebug = true;
6955
6956         R_View_Update();
6957         if (r_timereport_active)
6958                 R_TimeReport("visibility");
6959
6960         R_Shadow_UpdateBounceGridTexture();
6961         if (r_timereport_active && r_shadow_bouncegrid.integer)
6962                 R_TimeReport("bouncegrid");
6963
6964         r_fb.water.numwaterplanes = 0;
6965         if (r_fb.water.enabled)
6966                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6967
6968         R_RenderScene(fbo, depthtexture, colortexture);
6969         r_fb.water.numwaterplanes = 0;
6970
6971         R_BlendView(fbo, depthtexture, colortexture);
6972         if (r_timereport_active)
6973                 R_TimeReport("blendview");
6974
6975         GL_Scissor(0, 0, vid.width, vid.height);
6976         GL_ScissorTest(false);
6977
6978         r_refdef.view.matrix = originalmatrix;
6979
6980         CHECKGLERROR
6981 }
6982
6983 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6984 {
6985         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6986         {
6987                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6988                 if (r_timereport_active)
6989                         R_TimeReport("waterworld");
6990         }
6991
6992         // don't let sound skip if going slow
6993         if (r_refdef.scene.extraupdate)
6994                 S_ExtraUpdate ();
6995
6996         R_DrawModelsAddWaterPlanes();
6997         if (r_timereport_active)
6998                 R_TimeReport("watermodels");
6999
7000         if (r_fb.water.numwaterplanes)
7001         {
7002                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7003                 if (r_timereport_active)
7004                         R_TimeReport("waterscenes");
7005         }
7006 }
7007
7008 extern void R_DrawLightningBeams (void);
7009 extern void VM_CL_AddPolygonsToMeshQueue (void);
7010 extern void R_DrawPortals (void);
7011 extern cvar_t cl_locs_show;
7012 static void R_DrawLocs(void);
7013 static void R_DrawEntityBBoxes(void);
7014 static void R_DrawModelDecals(void);
7015 extern cvar_t cl_decals_newsystem;
7016 extern qboolean r_shadow_usingdeferredprepass;
7017 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7018 {
7019         qboolean shadowmapping = false;
7020
7021         if (r_timereport_active)
7022                 R_TimeReport("beginscene");
7023
7024         r_refdef.stats.renders++;
7025
7026         R_UpdateFog();
7027
7028         // don't let sound skip if going slow
7029         if (r_refdef.scene.extraupdate)
7030                 S_ExtraUpdate ();
7031
7032         R_MeshQueue_BeginScene();
7033
7034         R_SkyStartFrame();
7035
7036         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);
7037
7038         if (r_timereport_active)
7039                 R_TimeReport("skystartframe");
7040
7041         if (cl.csqc_vidvars.drawworld)
7042         {
7043                 // don't let sound skip if going slow
7044                 if (r_refdef.scene.extraupdate)
7045                         S_ExtraUpdate ();
7046
7047                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7048                 {
7049                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7050                         if (r_timereport_active)
7051                                 R_TimeReport("worldsky");
7052                 }
7053
7054                 if (R_DrawBrushModelsSky() && r_timereport_active)
7055                         R_TimeReport("bmodelsky");
7056
7057                 if (skyrendermasked && skyrenderlater)
7058                 {
7059                         // we have to force off the water clipping plane while rendering sky
7060                         R_SetupView(false, fbo, depthtexture, colortexture);
7061                         R_Sky();
7062                         R_SetupView(true, fbo, depthtexture, colortexture);
7063                         if (r_timereport_active)
7064                                 R_TimeReport("sky");
7065                 }
7066         }
7067
7068         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7069         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7070                 R_Shadow_PrepareModelShadows();
7071         if (r_timereport_active)
7072                 R_TimeReport("preparelights");
7073
7074         if (R_Shadow_ShadowMappingEnabled())
7075                 shadowmapping = true;
7076
7077         if (r_shadow_usingdeferredprepass)
7078                 R_Shadow_DrawPrepass();
7079
7080         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7081         {
7082                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7083                 if (r_timereport_active)
7084                         R_TimeReport("worlddepth");
7085         }
7086         if (r_depthfirst.integer >= 2)
7087         {
7088                 R_DrawModelsDepth();
7089                 if (r_timereport_active)
7090                         R_TimeReport("modeldepth");
7091         }
7092
7093         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7094         {
7095                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7096                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7097                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7098                 // don't let sound skip if going slow
7099                 if (r_refdef.scene.extraupdate)
7100                         S_ExtraUpdate ();
7101         }
7102
7103         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7104         {
7105                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7106                 if (r_timereport_active)
7107                         R_TimeReport("world");
7108         }
7109
7110         // don't let sound skip if going slow
7111         if (r_refdef.scene.extraupdate)
7112                 S_ExtraUpdate ();
7113
7114         R_DrawModels();
7115         if (r_timereport_active)
7116                 R_TimeReport("models");
7117
7118         // don't let sound skip if going slow
7119         if (r_refdef.scene.extraupdate)
7120                 S_ExtraUpdate ();
7121
7122         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7123         {
7124                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7125                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7126                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7127                 // don't let sound skip if going slow
7128                 if (r_refdef.scene.extraupdate)
7129                         S_ExtraUpdate ();
7130         }
7131
7132         if (!r_shadow_usingdeferredprepass)
7133         {
7134                 R_Shadow_DrawLights();
7135                 if (r_timereport_active)
7136                         R_TimeReport("rtlights");
7137         }
7138
7139         // don't let sound skip if going slow
7140         if (r_refdef.scene.extraupdate)
7141                 S_ExtraUpdate ();
7142
7143         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7144         {
7145                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7146                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7147                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7148                 // don't let sound skip if going slow
7149                 if (r_refdef.scene.extraupdate)
7150                         S_ExtraUpdate ();
7151         }
7152
7153         if (cl.csqc_vidvars.drawworld)
7154         {
7155                 if (cl_decals_newsystem.integer)
7156                 {
7157                         R_DrawModelDecals();
7158                         if (r_timereport_active)
7159                                 R_TimeReport("modeldecals");
7160                 }
7161                 else
7162                 {
7163                         R_DrawDecals();
7164                         if (r_timereport_active)
7165                                 R_TimeReport("decals");
7166                 }
7167
7168                 R_DrawParticles();
7169                 if (r_timereport_active)
7170                         R_TimeReport("particles");
7171
7172                 R_DrawExplosions();
7173                 if (r_timereport_active)
7174                         R_TimeReport("explosions");
7175
7176                 R_DrawLightningBeams();
7177                 if (r_timereport_active)
7178                         R_TimeReport("lightning");
7179         }
7180
7181         VM_CL_AddPolygonsToMeshQueue();
7182
7183         if (r_refdef.view.showdebug)
7184         {
7185                 if (cl_locs_show.integer)
7186                 {
7187                         R_DrawLocs();
7188                         if (r_timereport_active)
7189                                 R_TimeReport("showlocs");
7190                 }
7191
7192                 if (r_drawportals.integer)
7193                 {
7194                         R_DrawPortals();
7195                         if (r_timereport_active)
7196                                 R_TimeReport("portals");
7197                 }
7198
7199                 if (r_showbboxes.value > 0)
7200                 {
7201                         R_DrawEntityBBoxes();
7202                         if (r_timereport_active)
7203                                 R_TimeReport("bboxes");
7204                 }
7205         }
7206
7207         if (r_transparent.integer)
7208         {
7209                 R_MeshQueue_RenderTransparent();
7210                 if (r_timereport_active)
7211                         R_TimeReport("drawtrans");
7212         }
7213
7214         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))
7215         {
7216                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7217                 if (r_timereport_active)
7218                         R_TimeReport("worlddebug");
7219                 R_DrawModelsDebug();
7220                 if (r_timereport_active)
7221                         R_TimeReport("modeldebug");
7222         }
7223
7224         if (cl.csqc_vidvars.drawworld)
7225         {
7226                 R_Shadow_DrawCoronas();
7227                 if (r_timereport_active)
7228                         R_TimeReport("coronas");
7229         }
7230
7231 #if 0
7232         {
7233                 GL_DepthTest(false);
7234                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7235                 GL_Color(1, 1, 1, 1);
7236                 qglBegin(GL_POLYGON);
7237                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7238                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7239                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7240                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7241                 qglEnd();
7242                 qglBegin(GL_POLYGON);
7243                 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]);
7244                 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]);
7245                 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]);
7246                 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]);
7247                 qglEnd();
7248                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7249         }
7250 #endif
7251
7252         // don't let sound skip if going slow
7253         if (r_refdef.scene.extraupdate)
7254                 S_ExtraUpdate ();
7255 }
7256
7257 static const unsigned short bboxelements[36] =
7258 {
7259         5, 1, 3, 5, 3, 7,
7260         6, 2, 0, 6, 0, 4,
7261         7, 3, 2, 7, 2, 6,
7262         4, 0, 1, 4, 1, 5,
7263         4, 5, 7, 4, 7, 6,
7264         1, 0, 2, 1, 2, 3,
7265 };
7266
7267 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7268 {
7269         int i;
7270         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7271
7272         RSurf_ActiveWorldEntity();
7273
7274         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7275         GL_DepthMask(false);
7276         GL_DepthRange(0, 1);
7277         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7278 //      R_Mesh_ResetTextureState();
7279
7280         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7281         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7282         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7283         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7284         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7285         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7286         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7287         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7288         R_FillColors(color4f, 8, cr, cg, cb, ca);
7289         if (r_refdef.fogenabled)
7290         {
7291                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7292                 {
7293                         f1 = RSurf_FogVertex(v);
7294                         f2 = 1 - f1;
7295                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7296                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7297                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7298                 }
7299         }
7300         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7301         R_Mesh_ResetTextureState();
7302         R_SetupShader_Generic_NoTexture(false, false);
7303         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7304 }
7305
7306 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7307 {
7308         int i;
7309         float color[4];
7310         prvm_edict_t *edict;
7311         prvm_prog_t *prog_save = prog;
7312
7313         // this function draws bounding boxes of server entities
7314         if (!sv.active)
7315                 return;
7316
7317         GL_CullFace(GL_NONE);
7318         R_SetupShader_Generic_NoTexture(false, false);
7319
7320         prog = 0;
7321         SV_VM_Begin();
7322         for (i = 0;i < numsurfaces;i++)
7323         {
7324                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7325                 switch ((int)PRVM_serveredictfloat(edict, solid))
7326                 {
7327                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7328                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7329                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7330                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7331                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7332                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7333                 }
7334                 color[3] *= r_showbboxes.value;
7335                 color[3] = bound(0, color[3], 1);
7336                 GL_DepthTest(!r_showdisabledepthtest.integer);
7337                 GL_CullFace(r_refdef.view.cullface_front);
7338                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7339         }
7340         SV_VM_End();
7341         prog = prog_save;
7342 }
7343
7344 static void R_DrawEntityBBoxes(void)
7345 {
7346         int i;
7347         prvm_edict_t *edict;
7348         vec3_t center;
7349         prvm_prog_t *prog_save = prog;
7350
7351         // this function draws bounding boxes of server entities
7352         if (!sv.active)
7353                 return;
7354
7355         prog = 0;
7356         SV_VM_Begin();
7357         for (i = 0;i < prog->num_edicts;i++)
7358         {
7359                 edict = PRVM_EDICT_NUM(i);
7360                 if (edict->priv.server->free)
7361                         continue;
7362                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7363                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7364                         continue;
7365                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7366                         continue;
7367                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7368                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7369         }
7370         SV_VM_End();
7371         prog = prog_save;
7372 }
7373
7374 static const int nomodelelement3i[24] =
7375 {
7376         5, 2, 0,
7377         5, 1, 2,
7378         5, 0, 3,
7379         5, 3, 1,
7380         0, 2, 4,
7381         2, 1, 4,
7382         3, 0, 4,
7383         1, 3, 4
7384 };
7385
7386 static const unsigned short nomodelelement3s[24] =
7387 {
7388         5, 2, 0,
7389         5, 1, 2,
7390         5, 0, 3,
7391         5, 3, 1,
7392         0, 2, 4,
7393         2, 1, 4,
7394         3, 0, 4,
7395         1, 3, 4
7396 };
7397
7398 static const float nomodelvertex3f[6*3] =
7399 {
7400         -16,   0,   0,
7401          16,   0,   0,
7402           0, -16,   0,
7403           0,  16,   0,
7404           0,   0, -16,
7405           0,   0,  16
7406 };
7407
7408 static const float nomodelcolor4f[6*4] =
7409 {
7410         0.0f, 0.0f, 0.5f, 1.0f,
7411         0.0f, 0.0f, 0.5f, 1.0f,
7412         0.0f, 0.5f, 0.0f, 1.0f,
7413         0.0f, 0.5f, 0.0f, 1.0f,
7414         0.5f, 0.0f, 0.0f, 1.0f,
7415         0.5f, 0.0f, 0.0f, 1.0f
7416 };
7417
7418 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7419 {
7420         int i;
7421         float f1, f2, *c;
7422         float color4f[6*4];
7423
7424         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);
7425
7426         // this is only called once per entity so numsurfaces is always 1, and
7427         // surfacelist is always {0}, so this code does not handle batches
7428
7429         if (rsurface.ent_flags & RENDER_ADDITIVE)
7430         {
7431                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7432                 GL_DepthMask(false);
7433         }
7434         else if (rsurface.colormod[3] < 1)
7435         {
7436                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7437                 GL_DepthMask(false);
7438         }
7439         else
7440         {
7441                 GL_BlendFunc(GL_ONE, GL_ZERO);
7442                 GL_DepthMask(true);
7443         }
7444         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7445         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7446         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7447         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7448         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7449         for (i = 0, c = color4f;i < 6;i++, c += 4)
7450         {
7451                 c[0] *= rsurface.colormod[0];
7452                 c[1] *= rsurface.colormod[1];
7453                 c[2] *= rsurface.colormod[2];
7454                 c[3] *= rsurface.colormod[3];
7455         }
7456         if (r_refdef.fogenabled)
7457         {
7458                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7459                 {
7460                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7461                         f2 = 1 - f1;
7462                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7463                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7464                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7465                 }
7466         }
7467 //      R_Mesh_ResetTextureState();
7468         R_SetupShader_Generic_NoTexture(false, false);
7469         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7470         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7471 }
7472
7473 void R_DrawNoModel(entity_render_t *ent)
7474 {
7475         vec3_t org;
7476         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7477         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7478                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7479         else
7480                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7481 }
7482
7483 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7484 {
7485         vec3_t right1, right2, diff, normal;
7486
7487         VectorSubtract (org2, org1, normal);
7488
7489         // calculate 'right' vector for start
7490         VectorSubtract (r_refdef.view.origin, org1, diff);
7491         CrossProduct (normal, diff, right1);
7492         VectorNormalize (right1);
7493
7494         // calculate 'right' vector for end
7495         VectorSubtract (r_refdef.view.origin, org2, diff);
7496         CrossProduct (normal, diff, right2);
7497         VectorNormalize (right2);
7498
7499         vert[ 0] = org1[0] + width * right1[0];
7500         vert[ 1] = org1[1] + width * right1[1];
7501         vert[ 2] = org1[2] + width * right1[2];
7502         vert[ 3] = org1[0] - width * right1[0];
7503         vert[ 4] = org1[1] - width * right1[1];
7504         vert[ 5] = org1[2] - width * right1[2];
7505         vert[ 6] = org2[0] - width * right2[0];
7506         vert[ 7] = org2[1] - width * right2[1];
7507         vert[ 8] = org2[2] - width * right2[2];
7508         vert[ 9] = org2[0] + width * right2[0];
7509         vert[10] = org2[1] + width * right2[1];
7510         vert[11] = org2[2] + width * right2[2];
7511 }
7512
7513 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)
7514 {
7515         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7516         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7517         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7518         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7519         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7520         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7521         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7522         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7523         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7524         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7525         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7526         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7527 }
7528
7529 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7530 {
7531         int i;
7532         float *vertex3f;
7533         float v[3];
7534         VectorSet(v, x, y, z);
7535         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7536                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7537                         break;
7538         if (i == mesh->numvertices)
7539         {
7540                 if (mesh->numvertices < mesh->maxvertices)
7541                 {
7542                         VectorCopy(v, vertex3f);
7543                         mesh->numvertices++;
7544                 }
7545                 return mesh->numvertices;
7546         }
7547         else
7548                 return i;
7549 }
7550
7551 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7552 {
7553         int i;
7554         int *e, element[3];
7555         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7556         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7557         e = mesh->element3i + mesh->numtriangles * 3;
7558         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7559         {
7560                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7561                 if (mesh->numtriangles < mesh->maxtriangles)
7562                 {
7563                         *e++ = element[0];
7564                         *e++ = element[1];
7565                         *e++ = element[2];
7566                         mesh->numtriangles++;
7567                 }
7568                 element[1] = element[2];
7569         }
7570 }
7571
7572 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7573 {
7574         int i;
7575         int *e, element[3];
7576         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7577         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7578         e = mesh->element3i + mesh->numtriangles * 3;
7579         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7580         {
7581                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7582                 if (mesh->numtriangles < mesh->maxtriangles)
7583                 {
7584                         *e++ = element[0];
7585                         *e++ = element[1];
7586                         *e++ = element[2];
7587                         mesh->numtriangles++;
7588                 }
7589                 element[1] = element[2];
7590         }
7591 }
7592
7593 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7594 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7595 {
7596         int planenum, planenum2;
7597         int w;
7598         int tempnumpoints;
7599         mplane_t *plane, *plane2;
7600         double maxdist;
7601         double temppoints[2][256*3];
7602         // figure out how large a bounding box we need to properly compute this brush
7603         maxdist = 0;
7604         for (w = 0;w < numplanes;w++)
7605                 maxdist = max(maxdist, fabs(planes[w].dist));
7606         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7607         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7608         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7609         {
7610                 w = 0;
7611                 tempnumpoints = 4;
7612                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7613                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7614                 {
7615                         if (planenum2 == planenum)
7616                                 continue;
7617                         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);
7618                         w = !w;
7619                 }
7620                 if (tempnumpoints < 3)
7621                         continue;
7622                 // generate elements forming a triangle fan for this polygon
7623                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7624         }
7625 }
7626
7627 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)
7628 {
7629         texturelayer_t *layer;
7630         layer = t->currentlayers + t->currentnumlayers++;
7631         layer->type = type;
7632         layer->depthmask = depthmask;
7633         layer->blendfunc1 = blendfunc1;
7634         layer->blendfunc2 = blendfunc2;
7635         layer->texture = texture;
7636         layer->texmatrix = *matrix;
7637         layer->color[0] = r;
7638         layer->color[1] = g;
7639         layer->color[2] = b;
7640         layer->color[3] = a;
7641 }
7642
7643 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7644 {
7645         if(parms[0] == 0 && parms[1] == 0)
7646                 return false;
7647         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7648                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7649                         return false;
7650         return true;
7651 }
7652
7653 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7654 {
7655         double index, f;
7656         index = parms[2] + rsurface.shadertime * parms[3];
7657         index -= floor(index);
7658         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7659         {
7660         default:
7661         case Q3WAVEFUNC_NONE:
7662         case Q3WAVEFUNC_NOISE:
7663         case Q3WAVEFUNC_COUNT:
7664                 f = 0;
7665                 break;
7666         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7667         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7668         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7669         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7670         case Q3WAVEFUNC_TRIANGLE:
7671                 index *= 4;
7672                 f = index - floor(index);
7673                 if (index < 1)
7674                 {
7675                         // f = f;
7676                 }
7677                 else if (index < 2)
7678                         f = 1 - f;
7679                 else if (index < 3)
7680                         f = -f;
7681                 else
7682                         f = -(1 - f);
7683                 break;
7684         }
7685         f = parms[0] + parms[1] * f;
7686         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7687                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7688         return (float) f;
7689 }
7690
7691 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7692 {
7693         int w, h, idx;
7694         double f;
7695         double offsetd[2];
7696         float tcmat[12];
7697         matrix4x4_t matrix, temp;
7698         switch(tcmod->tcmod)
7699         {
7700                 case Q3TCMOD_COUNT:
7701                 case Q3TCMOD_NONE:
7702                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7703                                 matrix = r_waterscrollmatrix;
7704                         else
7705                                 matrix = identitymatrix;
7706                         break;
7707                 case Q3TCMOD_ENTITYTRANSLATE:
7708                         // this is used in Q3 to allow the gamecode to control texcoord
7709                         // scrolling on the entity, which is not supported in darkplaces yet.
7710                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7711                         break;
7712                 case Q3TCMOD_ROTATE:
7713                         f = tcmod->parms[0] * rsurface.shadertime;
7714                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7715                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7716                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7717                         break;
7718                 case Q3TCMOD_SCALE:
7719                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7720                         break;
7721                 case Q3TCMOD_SCROLL:
7722                         // extra care is needed because of precision breakdown with large values of time
7723                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7724                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7725                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7726                         break;
7727                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7728                         w = (int) tcmod->parms[0];
7729                         h = (int) tcmod->parms[1];
7730                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7731                         f = f - floor(f);
7732                         idx = (int) floor(f * w * h);
7733                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7734                         break;
7735                 case Q3TCMOD_STRETCH:
7736                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7737                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7738                         break;
7739                 case Q3TCMOD_TRANSFORM:
7740                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7741                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7742                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7743                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7744                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7745                         break;
7746                 case Q3TCMOD_TURBULENT:
7747                         // this is handled in the RSurf_PrepareVertices function
7748                         matrix = identitymatrix;
7749                         break;
7750         }
7751         temp = *texmatrix;
7752         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7753 }
7754
7755 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7756 {
7757         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7758         char name[MAX_QPATH];
7759         skinframe_t *skinframe;
7760         unsigned char pixels[296*194];
7761         strlcpy(cache->name, skinname, sizeof(cache->name));
7762         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7763         if (developer_loading.integer)
7764                 Con_Printf("loading %s\n", name);
7765         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7766         if (!skinframe || !skinframe->base)
7767         {
7768                 unsigned char *f;
7769                 fs_offset_t filesize;
7770                 skinframe = NULL;
7771                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7772                 if (f)
7773                 {
7774                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7775                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7776                         Mem_Free(f);
7777                 }
7778         }
7779         cache->skinframe = skinframe;
7780 }
7781
7782 texture_t *R_GetCurrentTexture(texture_t *t)
7783 {
7784         int i;
7785         const entity_render_t *ent = rsurface.entity;
7786         dp_model_t *model = ent->model;
7787         q3shaderinfo_layer_tcmod_t *tcmod;
7788
7789         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7790                 return t->currentframe;
7791         t->update_lastrenderframe = r_textureframe;
7792         t->update_lastrenderentity = (void *)ent;
7793
7794         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7795                 t->camera_entity = ent->entitynumber;
7796         else
7797                 t->camera_entity = 0;
7798
7799         // switch to an alternate material if this is a q1bsp animated material
7800         {
7801                 texture_t *texture = t;
7802                 int s = rsurface.ent_skinnum;
7803                 if ((unsigned int)s >= (unsigned int)model->numskins)
7804                         s = 0;
7805                 if (model->skinscenes)
7806                 {
7807                         if (model->skinscenes[s].framecount > 1)
7808                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7809                         else
7810                                 s = model->skinscenes[s].firstframe;
7811                 }
7812                 if (s > 0)
7813                         t = t + s * model->num_surfaces;
7814                 if (t->animated)
7815                 {
7816                         // use an alternate animation if the entity's frame is not 0,
7817                         // and only if the texture has an alternate animation
7818                         if (rsurface.ent_alttextures && t->anim_total[1])
7819                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7820                         else
7821                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7822                 }
7823                 texture->currentframe = t;
7824         }
7825
7826         // update currentskinframe to be a qw skin or animation frame
7827         if (rsurface.ent_qwskin >= 0)
7828         {
7829                 i = rsurface.ent_qwskin;
7830                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7831                 {
7832                         r_qwskincache_size = cl.maxclients;
7833                         if (r_qwskincache)
7834                                 Mem_Free(r_qwskincache);
7835                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7836                 }
7837                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7838                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7839                 t->currentskinframe = r_qwskincache[i].skinframe;
7840                 if (t->currentskinframe == NULL)
7841                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7842         }
7843         else if (t->numskinframes >= 2)
7844                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7845         if (t->backgroundnumskinframes >= 2)
7846                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7847
7848         t->currentmaterialflags = t->basematerialflags;
7849         t->currentalpha = rsurface.colormod[3];
7850         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7851                 t->currentalpha *= r_wateralpha.value;
7852         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7853                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7854         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7855                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7856         if (!(rsurface.ent_flags & RENDER_LIGHT))
7857                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7858         else if (FAKELIGHT_ENABLED)
7859         {
7860                 // no modellight if using fakelight for the map
7861         }
7862         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7863         {
7864                 // pick a model lighting mode
7865                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7866                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7867                 else
7868                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7869         }
7870         if (rsurface.ent_flags & RENDER_ADDITIVE)
7871                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7872         else if (t->currentalpha < 1)
7873                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7874         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7875         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7876                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7877         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7878                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7879         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7880                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7881         if (t->backgroundnumskinframes)
7882                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7883         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7884         {
7885                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7886                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7887         }
7888         else
7889                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7890         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7891         {
7892                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7893                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7894         }
7895         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7896                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7897
7898         // there is no tcmod
7899         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7900         {
7901                 t->currenttexmatrix = r_waterscrollmatrix;
7902                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7903         }
7904         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7905         {
7906                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7907                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7908         }
7909
7910         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7911                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7912         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7913                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7914
7915         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7916         if (t->currentskinframe->qpixels)
7917                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7918         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7919         if (!t->basetexture)
7920                 t->basetexture = r_texture_notexture;
7921         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7922         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7923         t->nmaptexture = t->currentskinframe->nmap;
7924         if (!t->nmaptexture)
7925                 t->nmaptexture = r_texture_blanknormalmap;
7926         t->glosstexture = r_texture_black;
7927         t->glowtexture = t->currentskinframe->glow;
7928         t->fogtexture = t->currentskinframe->fog;
7929         t->reflectmasktexture = t->currentskinframe->reflect;
7930         if (t->backgroundnumskinframes)
7931         {
7932                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7933                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7934                 t->backgroundglosstexture = r_texture_black;
7935                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7936                 if (!t->backgroundnmaptexture)
7937                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7938         }
7939         else
7940         {
7941                 t->backgroundbasetexture = r_texture_white;
7942                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7943                 t->backgroundglosstexture = r_texture_black;
7944                 t->backgroundglowtexture = NULL;
7945         }
7946         t->specularpower = r_shadow_glossexponent.value;
7947         // TODO: store reference values for these in the texture?
7948         t->specularscale = 0;
7949         if (r_shadow_gloss.integer > 0)
7950         {
7951                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7952                 {
7953                         if (r_shadow_glossintensity.value > 0)
7954                         {
7955                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7956                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7957                                 t->specularscale = r_shadow_glossintensity.value;
7958                         }
7959                 }
7960                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7961                 {
7962                         t->glosstexture = r_texture_white;
7963                         t->backgroundglosstexture = r_texture_white;
7964                         t->specularscale = r_shadow_gloss2intensity.value;
7965                         t->specularpower = r_shadow_gloss2exponent.value;
7966                 }
7967         }
7968         t->specularscale *= t->specularscalemod;
7969         t->specularpower *= t->specularpowermod;
7970         t->rtlightambient = 0;
7971
7972         // lightmaps mode looks bad with dlights using actual texturing, so turn
7973         // off the colormap and glossmap, but leave the normalmap on as it still
7974         // accurately represents the shading involved
7975         if (gl_lightmaps.integer)
7976         {
7977                 t->basetexture = r_texture_grey128;
7978                 t->pantstexture = r_texture_black;
7979                 t->shirttexture = r_texture_black;
7980                 t->nmaptexture = r_texture_blanknormalmap;
7981                 t->glosstexture = r_texture_black;
7982                 t->glowtexture = NULL;
7983                 t->fogtexture = NULL;
7984                 t->reflectmasktexture = NULL;
7985                 t->backgroundbasetexture = NULL;
7986                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7987                 t->backgroundglosstexture = r_texture_black;
7988                 t->backgroundglowtexture = NULL;
7989                 t->specularscale = 0;
7990                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7991         }
7992
7993         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7994         VectorClear(t->dlightcolor);
7995         t->currentnumlayers = 0;
7996         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7997         {
7998                 int blendfunc1, blendfunc2;
7999                 qboolean depthmask;
8000                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8001                 {
8002                         blendfunc1 = GL_SRC_ALPHA;
8003                         blendfunc2 = GL_ONE;
8004                 }
8005                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8006                 {
8007                         blendfunc1 = GL_SRC_ALPHA;
8008                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8009                 }
8010                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8011                 {
8012                         blendfunc1 = t->customblendfunc[0];
8013                         blendfunc2 = t->customblendfunc[1];
8014                 }
8015                 else
8016                 {
8017                         blendfunc1 = GL_ONE;
8018                         blendfunc2 = GL_ZERO;
8019                 }
8020                 // don't colormod evilblend textures
8021                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8022                         VectorSet(t->lightmapcolor, 1, 1, 1);
8023                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8024                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8025                 {
8026                         // fullbright is not affected by r_refdef.lightmapintensity
8027                         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]);
8028                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8029                                 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]);
8030                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8031                                 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]);
8032                 }
8033                 else
8034                 {
8035                         vec3_t ambientcolor;
8036                         float colorscale;
8037                         // set the color tint used for lights affecting this surface
8038                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8039                         colorscale = 2;
8040                         // q3bsp has no lightmap updates, so the lightstylevalue that
8041                         // would normally be baked into the lightmap must be
8042                         // applied to the color
8043                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8044                         if (model->type == mod_brushq3)
8045                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8046                         colorscale *= r_refdef.lightmapintensity;
8047                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8048                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8049                         // basic lit geometry
8050                         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]);
8051                         // add pants/shirt if needed
8052                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8053                                 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]);
8054                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8055                                 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]);
8056                         // now add ambient passes if needed
8057                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8058                         {
8059                                 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]);
8060                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8061                                         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]);
8062                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8063                                         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]);
8064                         }
8065                 }
8066                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8067                         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]);
8068                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8069                 {
8070                         // if this is opaque use alpha blend which will darken the earlier
8071                         // passes cheaply.
8072                         //
8073                         // if this is an alpha blended material, all the earlier passes
8074                         // were darkened by fog already, so we only need to add the fog
8075                         // color ontop through the fog mask texture
8076                         //
8077                         // if this is an additive blended material, all the earlier passes
8078                         // were darkened by fog already, and we should not add fog color
8079                         // (because the background was not darkened, there is no fog color
8080                         // that was lost behind it).
8081                         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]);
8082                 }
8083         }
8084
8085         return t->currentframe;
8086 }
8087
8088 rsurfacestate_t rsurface;
8089
8090 void RSurf_ActiveWorldEntity(void)
8091 {
8092         dp_model_t *model = r_refdef.scene.worldmodel;
8093         //if (rsurface.entity == r_refdef.scene.worldentity)
8094         //      return;
8095         rsurface.entity = r_refdef.scene.worldentity;
8096         rsurface.skeleton = NULL;
8097         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8098         rsurface.ent_skinnum = 0;
8099         rsurface.ent_qwskin = -1;
8100         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8101         rsurface.shadertime = r_refdef.scene.time;
8102         rsurface.matrix = identitymatrix;
8103         rsurface.inversematrix = identitymatrix;
8104         rsurface.matrixscale = 1;
8105         rsurface.inversematrixscale = 1;
8106         R_EntityMatrix(&identitymatrix);
8107         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8108         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8109         rsurface.fograngerecip = r_refdef.fograngerecip;
8110         rsurface.fogheightfade = r_refdef.fogheightfade;
8111         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8112         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8113         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8114         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8115         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8116         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8117         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8118         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8119         rsurface.colormod[3] = 1;
8120         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);
8121         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8122         rsurface.frameblend[0].lerp = 1;
8123         rsurface.ent_alttextures = false;
8124         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8125         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8126         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8127         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8129         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8130         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8132         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8133         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8135         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8136         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8138         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8139         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8141         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8142         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8144         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8145         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8146         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8147         rsurface.modelelement3i = model->surfmesh.data_element3i;
8148         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8149         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8150         rsurface.modelelement3s = model->surfmesh.data_element3s;
8151         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8152         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8153         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8154         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8155         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8156         rsurface.modelsurfaces = model->data_surfaces;
8157         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8158         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8159         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8160         rsurface.modelgeneratedvertex = false;
8161         rsurface.batchgeneratedvertex = false;
8162         rsurface.batchfirstvertex = 0;
8163         rsurface.batchnumvertices = 0;
8164         rsurface.batchfirsttriangle = 0;
8165         rsurface.batchnumtriangles = 0;
8166         rsurface.batchvertex3f  = NULL;
8167         rsurface.batchvertex3f_vertexbuffer = NULL;
8168         rsurface.batchvertex3f_bufferoffset = 0;
8169         rsurface.batchsvector3f = NULL;
8170         rsurface.batchsvector3f_vertexbuffer = NULL;
8171         rsurface.batchsvector3f_bufferoffset = 0;
8172         rsurface.batchtvector3f = NULL;
8173         rsurface.batchtvector3f_vertexbuffer = NULL;
8174         rsurface.batchtvector3f_bufferoffset = 0;
8175         rsurface.batchnormal3f  = NULL;
8176         rsurface.batchnormal3f_vertexbuffer = NULL;
8177         rsurface.batchnormal3f_bufferoffset = 0;
8178         rsurface.batchlightmapcolor4f = NULL;
8179         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8180         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8181         rsurface.batchtexcoordtexture2f = NULL;
8182         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8183         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8184         rsurface.batchtexcoordlightmap2f = NULL;
8185         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8186         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8187         rsurface.batchvertexmesh = NULL;
8188         rsurface.batchvertexmeshbuffer = NULL;
8189         rsurface.batchvertex3fbuffer = NULL;
8190         rsurface.batchelement3i = NULL;
8191         rsurface.batchelement3i_indexbuffer = NULL;
8192         rsurface.batchelement3i_bufferoffset = 0;
8193         rsurface.batchelement3s = NULL;
8194         rsurface.batchelement3s_indexbuffer = NULL;
8195         rsurface.batchelement3s_bufferoffset = 0;
8196         rsurface.passcolor4f = NULL;
8197         rsurface.passcolor4f_vertexbuffer = NULL;
8198         rsurface.passcolor4f_bufferoffset = 0;
8199 }
8200
8201 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8202 {
8203         dp_model_t *model = ent->model;
8204         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8205         //      return;
8206         rsurface.entity = (entity_render_t *)ent;
8207         rsurface.skeleton = ent->skeleton;
8208         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8209         rsurface.ent_skinnum = ent->skinnum;
8210         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;
8211         rsurface.ent_flags = ent->flags;
8212         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8213         rsurface.matrix = ent->matrix;
8214         rsurface.inversematrix = ent->inversematrix;
8215         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8216         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8217         R_EntityMatrix(&rsurface.matrix);
8218         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8219         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8220         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8221         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8222         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8223         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8224         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8225         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8226         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8227         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8228         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8229         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8230         rsurface.colormod[3] = ent->alpha;
8231         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8232         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8233         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8234         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8235         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8236         if (ent->model->brush.submodel && !prepass)
8237         {
8238                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8239                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8240         }
8241         if (model->surfmesh.isanimated && model->AnimateVertices)
8242         {
8243                 if (ent->animcache_vertex3f)
8244                 {
8245                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8246                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8247                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8248                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8249                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8250                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8251                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8252                 }
8253                 else if (wanttangents)
8254                 {
8255                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8256                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8257                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8258                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8260                         rsurface.modelvertexmesh = NULL;
8261                         rsurface.modelvertexmeshbuffer = NULL;
8262                         rsurface.modelvertex3fbuffer = NULL;
8263                 }
8264                 else if (wantnormals)
8265                 {
8266                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8267                         rsurface.modelsvector3f = NULL;
8268                         rsurface.modeltvector3f = NULL;
8269                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8270                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8271                         rsurface.modelvertexmesh = NULL;
8272                         rsurface.modelvertexmeshbuffer = NULL;
8273                         rsurface.modelvertex3fbuffer = NULL;
8274                 }
8275                 else
8276                 {
8277                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8278                         rsurface.modelsvector3f = NULL;
8279                         rsurface.modeltvector3f = NULL;
8280                         rsurface.modelnormal3f = NULL;
8281                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8282                         rsurface.modelvertexmesh = NULL;
8283                         rsurface.modelvertexmeshbuffer = NULL;
8284                         rsurface.modelvertex3fbuffer = NULL;
8285                 }
8286                 rsurface.modelvertex3f_vertexbuffer = 0;
8287                 rsurface.modelvertex3f_bufferoffset = 0;
8288                 rsurface.modelsvector3f_vertexbuffer = 0;
8289                 rsurface.modelsvector3f_bufferoffset = 0;
8290                 rsurface.modeltvector3f_vertexbuffer = 0;
8291                 rsurface.modeltvector3f_bufferoffset = 0;
8292                 rsurface.modelnormal3f_vertexbuffer = 0;
8293                 rsurface.modelnormal3f_bufferoffset = 0;
8294                 rsurface.modelgeneratedvertex = true;
8295         }
8296         else
8297         {
8298                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8299                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8300                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8301                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8302                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8303                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8304                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8305                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8307                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8308                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8309                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8310                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8311                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8312                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8313                 rsurface.modelgeneratedvertex = false;
8314         }
8315         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8316         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8317         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8318         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8319         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8320         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8321         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8322         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8323         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8324         rsurface.modelelement3i = model->surfmesh.data_element3i;
8325         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8326         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8327         rsurface.modelelement3s = model->surfmesh.data_element3s;
8328         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8329         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8330         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8331         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8332         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8333         rsurface.modelsurfaces = model->data_surfaces;
8334         rsurface.batchgeneratedvertex = false;
8335         rsurface.batchfirstvertex = 0;
8336         rsurface.batchnumvertices = 0;
8337         rsurface.batchfirsttriangle = 0;
8338         rsurface.batchnumtriangles = 0;
8339         rsurface.batchvertex3f  = NULL;
8340         rsurface.batchvertex3f_vertexbuffer = NULL;
8341         rsurface.batchvertex3f_bufferoffset = 0;
8342         rsurface.batchsvector3f = NULL;
8343         rsurface.batchsvector3f_vertexbuffer = NULL;
8344         rsurface.batchsvector3f_bufferoffset = 0;
8345         rsurface.batchtvector3f = NULL;
8346         rsurface.batchtvector3f_vertexbuffer = NULL;
8347         rsurface.batchtvector3f_bufferoffset = 0;
8348         rsurface.batchnormal3f  = NULL;
8349         rsurface.batchnormal3f_vertexbuffer = NULL;
8350         rsurface.batchnormal3f_bufferoffset = 0;
8351         rsurface.batchlightmapcolor4f = NULL;
8352         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8353         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8354         rsurface.batchtexcoordtexture2f = NULL;
8355         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8356         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8357         rsurface.batchtexcoordlightmap2f = NULL;
8358         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8359         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8360         rsurface.batchvertexmesh = NULL;
8361         rsurface.batchvertexmeshbuffer = NULL;
8362         rsurface.batchvertex3fbuffer = NULL;
8363         rsurface.batchelement3i = NULL;
8364         rsurface.batchelement3i_indexbuffer = NULL;
8365         rsurface.batchelement3i_bufferoffset = 0;
8366         rsurface.batchelement3s = NULL;
8367         rsurface.batchelement3s_indexbuffer = NULL;
8368         rsurface.batchelement3s_bufferoffset = 0;
8369         rsurface.passcolor4f = NULL;
8370         rsurface.passcolor4f_vertexbuffer = NULL;
8371         rsurface.passcolor4f_bufferoffset = 0;
8372 }
8373
8374 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)
8375 {
8376         rsurface.entity = r_refdef.scene.worldentity;
8377         rsurface.skeleton = NULL;
8378         rsurface.ent_skinnum = 0;
8379         rsurface.ent_qwskin = -1;
8380         rsurface.ent_flags = entflags;
8381         rsurface.shadertime = r_refdef.scene.time - shadertime;
8382         rsurface.modelnumvertices = numvertices;
8383         rsurface.modelnumtriangles = numtriangles;
8384         rsurface.matrix = *matrix;
8385         rsurface.inversematrix = *inversematrix;
8386         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8387         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8388         R_EntityMatrix(&rsurface.matrix);
8389         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8390         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8391         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8392         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8393         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8394         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8395         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8396         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8397         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8398         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8399         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8400         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8401         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);
8402         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8403         rsurface.frameblend[0].lerp = 1;
8404         rsurface.ent_alttextures = false;
8405         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8406         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8407         if (wanttangents)
8408         {
8409                 rsurface.modelvertex3f = (float *)vertex3f;
8410                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8411                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8412                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8413         }
8414         else if (wantnormals)
8415         {
8416                 rsurface.modelvertex3f = (float *)vertex3f;
8417                 rsurface.modelsvector3f = NULL;
8418                 rsurface.modeltvector3f = NULL;
8419                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8420         }
8421         else
8422         {
8423                 rsurface.modelvertex3f = (float *)vertex3f;
8424                 rsurface.modelsvector3f = NULL;
8425                 rsurface.modeltvector3f = NULL;
8426                 rsurface.modelnormal3f = NULL;
8427         }
8428         rsurface.modelvertexmesh = NULL;
8429         rsurface.modelvertexmeshbuffer = NULL;
8430         rsurface.modelvertex3fbuffer = NULL;
8431         rsurface.modelvertex3f_vertexbuffer = 0;
8432         rsurface.modelvertex3f_bufferoffset = 0;
8433         rsurface.modelsvector3f_vertexbuffer = 0;
8434         rsurface.modelsvector3f_bufferoffset = 0;
8435         rsurface.modeltvector3f_vertexbuffer = 0;
8436         rsurface.modeltvector3f_bufferoffset = 0;
8437         rsurface.modelnormal3f_vertexbuffer = 0;
8438         rsurface.modelnormal3f_bufferoffset = 0;
8439         rsurface.modelgeneratedvertex = true;
8440         rsurface.modellightmapcolor4f  = (float *)color4f;
8441         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8442         rsurface.modellightmapcolor4f_bufferoffset = 0;
8443         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8444         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8445         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8446         rsurface.modeltexcoordlightmap2f  = NULL;
8447         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8448         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8449         rsurface.modelelement3i = (int *)element3i;
8450         rsurface.modelelement3i_indexbuffer = NULL;
8451         rsurface.modelelement3i_bufferoffset = 0;
8452         rsurface.modelelement3s = (unsigned short *)element3s;
8453         rsurface.modelelement3s_indexbuffer = NULL;
8454         rsurface.modelelement3s_bufferoffset = 0;
8455         rsurface.modellightmapoffsets = NULL;
8456         rsurface.modelsurfaces = NULL;
8457         rsurface.batchgeneratedvertex = false;
8458         rsurface.batchfirstvertex = 0;
8459         rsurface.batchnumvertices = 0;
8460         rsurface.batchfirsttriangle = 0;
8461         rsurface.batchnumtriangles = 0;
8462         rsurface.batchvertex3f  = NULL;
8463         rsurface.batchvertex3f_vertexbuffer = NULL;
8464         rsurface.batchvertex3f_bufferoffset = 0;
8465         rsurface.batchsvector3f = NULL;
8466         rsurface.batchsvector3f_vertexbuffer = NULL;
8467         rsurface.batchsvector3f_bufferoffset = 0;
8468         rsurface.batchtvector3f = NULL;
8469         rsurface.batchtvector3f_vertexbuffer = NULL;
8470         rsurface.batchtvector3f_bufferoffset = 0;
8471         rsurface.batchnormal3f  = NULL;
8472         rsurface.batchnormal3f_vertexbuffer = NULL;
8473         rsurface.batchnormal3f_bufferoffset = 0;
8474         rsurface.batchlightmapcolor4f = NULL;
8475         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8476         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8477         rsurface.batchtexcoordtexture2f = NULL;
8478         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8479         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8480         rsurface.batchtexcoordlightmap2f = NULL;
8481         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8482         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8483         rsurface.batchvertexmesh = NULL;
8484         rsurface.batchvertexmeshbuffer = NULL;
8485         rsurface.batchvertex3fbuffer = NULL;
8486         rsurface.batchelement3i = NULL;
8487         rsurface.batchelement3i_indexbuffer = NULL;
8488         rsurface.batchelement3i_bufferoffset = 0;
8489         rsurface.batchelement3s = NULL;
8490         rsurface.batchelement3s_indexbuffer = NULL;
8491         rsurface.batchelement3s_bufferoffset = 0;
8492         rsurface.passcolor4f = NULL;
8493         rsurface.passcolor4f_vertexbuffer = NULL;
8494         rsurface.passcolor4f_bufferoffset = 0;
8495
8496         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8497         {
8498                 if ((wantnormals || wanttangents) && !normal3f)
8499                 {
8500                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8501                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8502                 }
8503                 if (wanttangents && !svector3f)
8504                 {
8505                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8506                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8507                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8508                 }
8509         }
8510 }
8511
8512 float RSurf_FogPoint(const float *v)
8513 {
8514         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8515         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8516         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8517         float FogHeightFade = r_refdef.fogheightfade;
8518         float fogfrac;
8519         unsigned int fogmasktableindex;
8520         if (r_refdef.fogplaneviewabove)
8521                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8522         else
8523                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8524         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8525         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8526 }
8527
8528 float RSurf_FogVertex(const float *v)
8529 {
8530         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8531         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8532         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8533         float FogHeightFade = rsurface.fogheightfade;
8534         float fogfrac;
8535         unsigned int fogmasktableindex;
8536         if (r_refdef.fogplaneviewabove)
8537                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8538         else
8539                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8540         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8541         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8542 }
8543
8544 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8545 {
8546         int i;
8547         for (i = 0;i < numelements;i++)
8548                 outelement3i[i] = inelement3i[i] + adjust;
8549 }
8550
8551 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8552 extern cvar_t gl_vbo;
8553 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8554 {
8555         int deformindex;
8556         int firsttriangle;
8557         int numtriangles;
8558         int firstvertex;
8559         int endvertex;
8560         int numvertices;
8561         int surfacefirsttriangle;
8562         int surfacenumtriangles;
8563         int surfacefirstvertex;
8564         int surfaceendvertex;
8565         int surfacenumvertices;
8566         int batchnumvertices;
8567         int batchnumtriangles;
8568         int needsupdate;
8569         int i, j;
8570         qboolean gaps;
8571         qboolean dynamicvertex;
8572         float amplitude;
8573         float animpos;
8574         float scale;
8575         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8576         float waveparms[4];
8577         q3shaderinfo_deform_t *deform;
8578         const msurface_t *surface, *firstsurface;
8579         r_vertexmesh_t *vertexmesh;
8580         if (!texturenumsurfaces)
8581                 return;
8582         // find vertex range of this surface batch
8583         gaps = false;
8584         firstsurface = texturesurfacelist[0];
8585         firsttriangle = firstsurface->num_firsttriangle;
8586         batchnumvertices = 0;
8587         batchnumtriangles = 0;
8588         firstvertex = endvertex = firstsurface->num_firstvertex;
8589         for (i = 0;i < texturenumsurfaces;i++)
8590         {
8591                 surface = texturesurfacelist[i];
8592                 if (surface != firstsurface + i)
8593                         gaps = true;
8594                 surfacefirstvertex = surface->num_firstvertex;
8595                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8596                 surfacenumvertices = surface->num_vertices;
8597                 surfacenumtriangles = surface->num_triangles;
8598                 if (firstvertex > surfacefirstvertex)
8599                         firstvertex = surfacefirstvertex;
8600                 if (endvertex < surfaceendvertex)
8601                         endvertex = surfaceendvertex;
8602                 batchnumvertices += surfacenumvertices;
8603                 batchnumtriangles += surfacenumtriangles;
8604         }
8605
8606         // we now know the vertex range used, and if there are any gaps in it
8607         rsurface.batchfirstvertex = firstvertex;
8608         rsurface.batchnumvertices = endvertex - firstvertex;
8609         rsurface.batchfirsttriangle = firsttriangle;
8610         rsurface.batchnumtriangles = batchnumtriangles;
8611
8612         // this variable holds flags for which properties have been updated that
8613         // may require regenerating vertexmesh array...
8614         needsupdate = 0;
8615
8616         // check if any dynamic vertex processing must occur
8617         dynamicvertex = false;
8618
8619         // if there is a chance of animated vertex colors, it's a dynamic batch
8620         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8621         {
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8625         }
8626
8627         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8628         {
8629                 switch (deform->deform)
8630                 {
8631                 default:
8632                 case Q3DEFORM_PROJECTIONSHADOW:
8633                 case Q3DEFORM_TEXT0:
8634                 case Q3DEFORM_TEXT1:
8635                 case Q3DEFORM_TEXT2:
8636                 case Q3DEFORM_TEXT3:
8637                 case Q3DEFORM_TEXT4:
8638                 case Q3DEFORM_TEXT5:
8639                 case Q3DEFORM_TEXT6:
8640                 case Q3DEFORM_TEXT7:
8641                 case Q3DEFORM_NONE:
8642                         break;
8643                 case Q3DEFORM_AUTOSPRITE:
8644                         dynamicvertex = true;
8645                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8646                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8647                         break;
8648                 case Q3DEFORM_AUTOSPRITE2:
8649                         dynamicvertex = true;
8650                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8652                         break;
8653                 case Q3DEFORM_NORMAL:
8654                         dynamicvertex = true;
8655                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8656                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8657                         break;
8658                 case Q3DEFORM_WAVE:
8659                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8660                                 break; // if wavefunc is a nop, ignore this transform
8661                         dynamicvertex = true;
8662                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8663                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8664                         break;
8665                 case Q3DEFORM_BULGE:
8666                         dynamicvertex = true;
8667                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8668                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8669                         break;
8670                 case Q3DEFORM_MOVE:
8671                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8672                                 break; // if wavefunc is a nop, ignore this transform
8673                         dynamicvertex = true;
8674                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8675                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8676                         break;
8677                 }
8678         }
8679         switch(rsurface.texture->tcgen.tcgen)
8680         {
8681         default:
8682         case Q3TCGEN_TEXTURE:
8683                 break;
8684         case Q3TCGEN_LIGHTMAP:
8685                 dynamicvertex = true;
8686                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8687                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8688                 break;
8689         case Q3TCGEN_VECTOR:
8690                 dynamicvertex = true;
8691                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8692                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8693                 break;
8694         case Q3TCGEN_ENVIRONMENT:
8695                 dynamicvertex = true;
8696                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8697                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8698                 break;
8699         }
8700         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8701         {
8702                 dynamicvertex = true;
8703                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8704                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8705         }
8706
8707         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8708         {
8709                 dynamicvertex = true;
8710                 batchneed |= BATCHNEED_NOGAPS;
8711                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8712         }
8713
8714         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8715         {
8716                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8717                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8718                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8719                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8721                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8722                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8723         }
8724
8725         // when the model data has no vertex buffer (dynamic mesh), we need to
8726         // eliminate gaps
8727         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8728                 batchneed |= BATCHNEED_NOGAPS;
8729
8730         // if needsupdate, we have to do a dynamic vertex batch for sure
8731         if (needsupdate & batchneed)
8732                 dynamicvertex = true;
8733
8734         // see if we need to build vertexmesh from arrays
8735         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8736                 dynamicvertex = true;
8737
8738         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8739         // also some drivers strongly dislike firstvertex
8740         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8741                 dynamicvertex = true;
8742
8743         rsurface.batchvertex3f = rsurface.modelvertex3f;
8744         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8745         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8746         rsurface.batchsvector3f = rsurface.modelsvector3f;
8747         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8748         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8749         rsurface.batchtvector3f = rsurface.modeltvector3f;
8750         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8751         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8752         rsurface.batchnormal3f = rsurface.modelnormal3f;
8753         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8754         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8755         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8756         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8757         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8758         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8759         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8760         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8761         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8762         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8763         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8764         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8765         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8766         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8767         rsurface.batchelement3i = rsurface.modelelement3i;
8768         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8769         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8770         rsurface.batchelement3s = rsurface.modelelement3s;
8771         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8772         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8773
8774         // if any dynamic vertex processing has to occur in software, we copy the
8775         // entire surface list together before processing to rebase the vertices
8776         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8777         //
8778         // if any gaps exist and we do not have a static vertex buffer, we have to
8779         // copy the surface list together to avoid wasting upload bandwidth on the
8780         // vertices in the gaps.
8781         //
8782         // if gaps exist and we have a static vertex buffer, we still have to
8783         // combine the index buffer ranges into one dynamic index buffer.
8784         //
8785         // in all cases we end up with data that can be drawn in one call.
8786
8787         if (!dynamicvertex)
8788         {
8789                 // static vertex data, just set pointers...
8790                 rsurface.batchgeneratedvertex = false;
8791                 // if there are gaps, we want to build a combined index buffer,
8792                 // otherwise use the original static buffer with an appropriate offset
8793                 if (gaps)
8794                 {
8795                         // build a new triangle elements array for this batch
8796                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8797                         rsurface.batchfirsttriangle = 0;
8798                         numtriangles = 0;
8799                         for (i = 0;i < texturenumsurfaces;i++)
8800                         {
8801                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8802                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8803                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8804                                 numtriangles += surfacenumtriangles;
8805                         }
8806                         rsurface.batchelement3i_indexbuffer = NULL;
8807                         rsurface.batchelement3i_bufferoffset = 0;
8808                         rsurface.batchelement3s = NULL;
8809                         rsurface.batchelement3s_indexbuffer = NULL;
8810                         rsurface.batchelement3s_bufferoffset = 0;
8811                         if (endvertex <= 65536)
8812                         {
8813                                 // make a 16bit (unsigned short) index array if possible
8814                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8815                                 for (i = 0;i < numtriangles*3;i++)
8816                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8817                         }
8818                 }
8819                 return;
8820         }
8821
8822         // something needs software processing, do it for real...
8823         // we only directly handle separate array data in this case and then
8824         // generate interleaved data if needed...
8825         rsurface.batchgeneratedvertex = true;
8826
8827         // now copy the vertex data into a combined array and make an index array
8828         // (this is what Quake3 does all the time)
8829         //if (gaps || rsurface.batchfirstvertex)
8830         {
8831                 rsurface.batchvertex3fbuffer = NULL;
8832                 rsurface.batchvertexmesh = NULL;
8833                 rsurface.batchvertexmeshbuffer = NULL;
8834                 rsurface.batchvertex3f = NULL;
8835                 rsurface.batchvertex3f_vertexbuffer = NULL;
8836                 rsurface.batchvertex3f_bufferoffset = 0;
8837                 rsurface.batchsvector3f = NULL;
8838                 rsurface.batchsvector3f_vertexbuffer = NULL;
8839                 rsurface.batchsvector3f_bufferoffset = 0;
8840                 rsurface.batchtvector3f = NULL;
8841                 rsurface.batchtvector3f_vertexbuffer = NULL;
8842                 rsurface.batchtvector3f_bufferoffset = 0;
8843                 rsurface.batchnormal3f = NULL;
8844                 rsurface.batchnormal3f_vertexbuffer = NULL;
8845                 rsurface.batchnormal3f_bufferoffset = 0;
8846                 rsurface.batchlightmapcolor4f = NULL;
8847                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8848                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8849                 rsurface.batchtexcoordtexture2f = NULL;
8850                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8851                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8852                 rsurface.batchtexcoordlightmap2f = NULL;
8853                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8854                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8855                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8856                 rsurface.batchelement3i_indexbuffer = NULL;
8857                 rsurface.batchelement3i_bufferoffset = 0;
8858                 rsurface.batchelement3s = NULL;
8859                 rsurface.batchelement3s_indexbuffer = NULL;
8860                 rsurface.batchelement3s_bufferoffset = 0;
8861                 // we'll only be setting up certain arrays as needed
8862                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8863                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8864                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8865                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8866                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8867                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8868                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8869                 {
8870                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8871                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8872                 }
8873                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8874                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8875                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8876                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8877                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8878                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8879                 numvertices = 0;
8880                 numtriangles = 0;
8881                 for (i = 0;i < texturenumsurfaces;i++)
8882                 {
8883                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8884                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8885                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8886                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8887                         // copy only the data requested
8888                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8889                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8890                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8891                         {
8892                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8893                                 {
8894                                         if (rsurface.batchvertex3f)
8895                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8896                                         else
8897                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8898                                 }
8899                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8900                                 {
8901                                         if (rsurface.modelnormal3f)
8902                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8903                                         else
8904                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8905                                 }
8906                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8907                                 {
8908                                         if (rsurface.modelsvector3f)
8909                                         {
8910                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8911                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8912                                         }
8913                                         else
8914                                         {
8915                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8916                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8917                                         }
8918                                 }
8919                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8920                                 {
8921                                         if (rsurface.modellightmapcolor4f)
8922                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8923                                         else
8924                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8925                                 }
8926                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8927                                 {
8928                                         if (rsurface.modeltexcoordtexture2f)
8929                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8930                                         else
8931                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8932                                 }
8933                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8934                                 {
8935                                         if (rsurface.modeltexcoordlightmap2f)
8936                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8937                                         else
8938                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8939                                 }
8940                         }
8941                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8942                         numvertices += surfacenumvertices;
8943                         numtriangles += surfacenumtriangles;
8944                 }
8945
8946                 // generate a 16bit index array as well if possible
8947                 // (in general, dynamic batches fit)
8948                 if (numvertices <= 65536)
8949                 {
8950                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8951                         for (i = 0;i < numtriangles*3;i++)
8952                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8953                 }
8954
8955                 // since we've copied everything, the batch now starts at 0
8956                 rsurface.batchfirstvertex = 0;
8957                 rsurface.batchnumvertices = batchnumvertices;
8958                 rsurface.batchfirsttriangle = 0;
8959                 rsurface.batchnumtriangles = batchnumtriangles;
8960         }
8961
8962         // q1bsp surfaces rendered in vertex color mode have to have colors
8963         // calculated based on lightstyles
8964         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8965         {
8966                 // generate color arrays for the surfaces in this list
8967                 int c[4];
8968                 int scale;
8969                 int size3;
8970                 const int *offsets;
8971                 const unsigned char *lm;
8972                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8973                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8974                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8975                 numvertices = 0;
8976                 for (i = 0;i < texturenumsurfaces;i++)
8977                 {
8978                         surface = texturesurfacelist[i];
8979                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8980                         surfacenumvertices = surface->num_vertices;
8981                         if (surface->lightmapinfo->samples)
8982                         {
8983                                 for (j = 0;j < surfacenumvertices;j++)
8984                                 {
8985                                         lm = surface->lightmapinfo->samples + offsets[j];
8986                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8987                                         VectorScale(lm, scale, c);
8988                                         if (surface->lightmapinfo->styles[1] != 255)
8989                                         {
8990                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8991                                                 lm += size3;
8992                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8993                                                 VectorMA(c, scale, lm, c);
8994                                                 if (surface->lightmapinfo->styles[2] != 255)
8995                                                 {
8996                                                         lm += size3;
8997                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8998                                                         VectorMA(c, scale, lm, c);
8999                                                         if (surface->lightmapinfo->styles[3] != 255)
9000                                                         {
9001                                                                 lm += size3;
9002                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9003                                                                 VectorMA(c, scale, lm, c);
9004                                                         }
9005                                                 }
9006                                         }
9007                                         c[0] >>= 7;
9008                                         c[1] >>= 7;
9009                                         c[2] >>= 7;
9010                                         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);
9011                                         numvertices++;
9012                                 }
9013                         }
9014                         else
9015                         {
9016                                 for (j = 0;j < surfacenumvertices;j++)
9017                                 {
9018                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9019                                         numvertices++;
9020                                 }
9021                         }
9022                 }
9023         }
9024
9025         // if vertices are deformed (sprite flares and things in maps, possibly
9026         // water waves, bulges and other deformations), modify the copied vertices
9027         // in place
9028         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9029         {
9030                 switch (deform->deform)
9031                 {
9032                 default:
9033                 case Q3DEFORM_PROJECTIONSHADOW:
9034                 case Q3DEFORM_TEXT0:
9035                 case Q3DEFORM_TEXT1:
9036                 case Q3DEFORM_TEXT2:
9037                 case Q3DEFORM_TEXT3:
9038                 case Q3DEFORM_TEXT4:
9039                 case Q3DEFORM_TEXT5:
9040                 case Q3DEFORM_TEXT6:
9041                 case Q3DEFORM_TEXT7:
9042                 case Q3DEFORM_NONE:
9043                         break;
9044                 case Q3DEFORM_AUTOSPRITE:
9045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9046                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9047                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9048                         VectorNormalize(newforward);
9049                         VectorNormalize(newright);
9050                         VectorNormalize(newup);
9051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9053 //                      rsurface.batchvertex3f_bufferoffset = 0;
9054 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9055 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9056 //                      rsurface.batchsvector3f_bufferoffset = 0;
9057 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9058 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9059 //                      rsurface.batchtvector3f_bufferoffset = 0;
9060 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9061 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9062 //                      rsurface.batchnormal3f_bufferoffset = 0;
9063                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9064                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9065                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9066                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9067                                 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);
9068                         // a single autosprite surface can contain multiple sprites...
9069                         for (j = 0;j < batchnumvertices - 3;j += 4)
9070                         {
9071                                 VectorClear(center);
9072                                 for (i = 0;i < 4;i++)
9073                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9074                                 VectorScale(center, 0.25f, center);
9075                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9076                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9077                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9078                                 for (i = 0;i < 4;i++)
9079                                 {
9080                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9081                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9082                                 }
9083                         }
9084                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9085                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9086                         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);
9087                         break;
9088                 case Q3DEFORM_AUTOSPRITE2:
9089                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9090                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9091                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9092                         VectorNormalize(newforward);
9093                         VectorNormalize(newright);
9094                         VectorNormalize(newup);
9095 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9096 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9097 //                      rsurface.batchvertex3f_bufferoffset = 0;
9098                         {
9099                                 const float *v1, *v2;
9100                                 vec3_t start, end;
9101                                 float f, l;
9102                                 struct
9103                                 {
9104                                         float length2;
9105                                         const float *v1;
9106                                         const float *v2;
9107                                 }
9108                                 shortest[2];
9109                                 memset(shortest, 0, sizeof(shortest));
9110                                 // a single autosprite surface can contain multiple sprites...
9111                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9112                                 {
9113                                         VectorClear(center);
9114                                         for (i = 0;i < 4;i++)
9115                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9116                                         VectorScale(center, 0.25f, center);
9117                                         // find the two shortest edges, then use them to define the
9118                                         // axis vectors for rotating around the central axis
9119                                         for (i = 0;i < 6;i++)
9120                                         {
9121                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9122                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9123                                                 l = VectorDistance2(v1, v2);
9124                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9125                                                 if (v1[2] != v2[2])
9126                                                         l += (1.0f / 1024.0f);
9127                                                 if (shortest[0].length2 > l || i == 0)
9128                                                 {
9129                                                         shortest[1] = shortest[0];
9130                                                         shortest[0].length2 = l;
9131                                                         shortest[0].v1 = v1;
9132                                                         shortest[0].v2 = v2;
9133                                                 }
9134                                                 else if (shortest[1].length2 > l || i == 1)
9135                                                 {
9136                                                         shortest[1].length2 = l;
9137                                                         shortest[1].v1 = v1;
9138                                                         shortest[1].v2 = v2;
9139                                                 }
9140                                         }
9141                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9142                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9143                                         // this calculates the right vector from the shortest edge
9144                                         // and the up vector from the edge midpoints
9145                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9146                                         VectorNormalize(right);
9147                                         VectorSubtract(end, start, up);
9148                                         VectorNormalize(up);
9149                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9150                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9151                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9152                                         VectorNegate(forward, forward);
9153                                         VectorReflect(forward, 0, up, forward);
9154                                         VectorNormalize(forward);
9155                                         CrossProduct(up, forward, newright);
9156                                         VectorNormalize(newright);
9157                                         // rotate the quad around the up axis vector, this is made
9158                                         // especially easy by the fact we know the quad is flat,
9159                                         // so we only have to subtract the center position and
9160                                         // measure distance along the right vector, and then
9161                                         // multiply that by the newright vector and add back the
9162                                         // center position
9163                                         // we also need to subtract the old position to undo the
9164                                         // displacement from the center, which we do with a
9165                                         // DotProduct, the subtraction/addition of center is also
9166                                         // optimized into DotProducts here
9167                                         l = DotProduct(right, center);
9168                                         for (i = 0;i < 4;i++)
9169                                         {
9170                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9171                                                 f = DotProduct(right, v1) - l;
9172                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9173                                         }
9174                                 }
9175                         }
9176                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9177                         {
9178 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9179 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9180 //                              rsurface.batchnormal3f_bufferoffset = 0;
9181                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9182                         }
9183                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9184                         {
9185 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9186 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9187 //                              rsurface.batchsvector3f_bufferoffset = 0;
9188 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9190 //                              rsurface.batchtvector3f_bufferoffset = 0;
9191                                 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);
9192                         }
9193                         break;
9194                 case Q3DEFORM_NORMAL:
9195                         // deform the normals to make reflections wavey
9196                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9197                         rsurface.batchnormal3f_vertexbuffer = NULL;
9198                         rsurface.batchnormal3f_bufferoffset = 0;
9199                         for (j = 0;j < batchnumvertices;j++)
9200                         {
9201                                 float vertex[3];
9202                                 float *normal = rsurface.batchnormal3f + 3*j;
9203                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9204                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9205                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9206                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9207                                 VectorNormalize(normal);
9208                         }
9209                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9210                         {
9211 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9212 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9213 //                              rsurface.batchsvector3f_bufferoffset = 0;
9214 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9215 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9216 //                              rsurface.batchtvector3f_bufferoffset = 0;
9217                                 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);
9218                         }
9219                         break;
9220                 case Q3DEFORM_WAVE:
9221                         // deform vertex array to make wavey water and flags and such
9222                         waveparms[0] = deform->waveparms[0];
9223                         waveparms[1] = deform->waveparms[1];
9224                         waveparms[2] = deform->waveparms[2];
9225                         waveparms[3] = deform->waveparms[3];
9226                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9227                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9228                         // this is how a divisor of vertex influence on deformation
9229                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9230                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9231 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9232 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9233 //                      rsurface.batchvertex3f_bufferoffset = 0;
9234 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9235 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9236 //                      rsurface.batchnormal3f_bufferoffset = 0;
9237                         for (j = 0;j < batchnumvertices;j++)
9238                         {
9239                                 // if the wavefunc depends on time, evaluate it per-vertex
9240                                 if (waveparms[3])
9241                                 {
9242                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9243                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9244                                 }
9245                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9246                         }
9247                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9248                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9249                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9250                         {
9251 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9252 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9253 //                              rsurface.batchsvector3f_bufferoffset = 0;
9254 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9255 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9256 //                              rsurface.batchtvector3f_bufferoffset = 0;
9257                                 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);
9258                         }
9259                         break;
9260                 case Q3DEFORM_BULGE:
9261                         // deform vertex array to make the surface have moving bulges
9262 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9263 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9264 //                      rsurface.batchvertex3f_bufferoffset = 0;
9265 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9266 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9267 //                      rsurface.batchnormal3f_bufferoffset = 0;
9268                         for (j = 0;j < batchnumvertices;j++)
9269                         {
9270                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9271                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9272                         }
9273                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9274                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9275                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9276                         {
9277 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9278 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9279 //                              rsurface.batchsvector3f_bufferoffset = 0;
9280 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9281 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9282 //                              rsurface.batchtvector3f_bufferoffset = 0;
9283                                 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);
9284                         }
9285                         break;
9286                 case Q3DEFORM_MOVE:
9287                         // deform vertex array
9288                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9289                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9290                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9291                         VectorScale(deform->parms, scale, waveparms);
9292 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9293 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9294 //                      rsurface.batchvertex3f_bufferoffset = 0;
9295                         for (j = 0;j < batchnumvertices;j++)
9296                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9297                         break;
9298                 }
9299         }
9300
9301         // generate texcoords based on the chosen texcoord source
9302         switch(rsurface.texture->tcgen.tcgen)
9303         {
9304         default:
9305         case Q3TCGEN_TEXTURE:
9306                 break;
9307         case Q3TCGEN_LIGHTMAP:
9308 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9309 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9310 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9311                 if (rsurface.batchtexcoordlightmap2f)
9312                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9313                 break;
9314         case Q3TCGEN_VECTOR:
9315 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9316 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9317 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9318                 for (j = 0;j < batchnumvertices;j++)
9319                 {
9320                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9321                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9322                 }
9323                 break;
9324         case Q3TCGEN_ENVIRONMENT:
9325                 // make environment reflections using a spheremap
9326                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9327                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9328                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9329                 for (j = 0;j < batchnumvertices;j++)
9330                 {
9331                         // identical to Q3A's method, but executed in worldspace so
9332                         // carried models can be shiny too
9333
9334                         float viewer[3], d, reflected[3], worldreflected[3];
9335
9336                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9337                         // VectorNormalize(viewer);
9338
9339                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9340
9341                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9342                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9343                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9344                         // note: this is proportinal to viewer, so we can normalize later
9345
9346                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9347                         VectorNormalize(worldreflected);
9348
9349                         // note: this sphere map only uses world x and z!
9350                         // so positive and negative y will LOOK THE SAME.
9351                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9352                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9353                 }
9354                 break;
9355         }
9356         // the only tcmod that needs software vertex processing is turbulent, so
9357         // check for it here and apply the changes if needed
9358         // and we only support that as the first one
9359         // (handling a mixture of turbulent and other tcmods would be problematic
9360         //  without punting it entirely to a software path)
9361         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9362         {
9363                 amplitude = rsurface.texture->tcmods[0].parms[1];
9364                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9365 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9366 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9367 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9368                 for (j = 0;j < batchnumvertices;j++)
9369                 {
9370                         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);
9371                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9372                 }
9373         }
9374
9375         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9376         {
9377                 // convert the modified arrays to vertex structs
9378 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9379 //              rsurface.batchvertexmeshbuffer = NULL;
9380                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9381                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9382                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9383                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9384                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9385                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9386                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9387                 {
9388                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9389                         {
9390                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9391                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9392                         }
9393                 }
9394                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9395                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9396                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9397                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9398                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9399                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9400                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9401                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9402                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9403         }
9404 }
9405
9406 void RSurf_DrawBatch(void)
9407 {
9408         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9409         // through the pipeline, killing it earlier in the pipeline would have
9410         // per-surface overhead rather than per-batch overhead, so it's best to
9411         // reject it here, before it hits glDraw.
9412         if (rsurface.batchnumtriangles == 0)
9413                 return;
9414 #if 0
9415         // batch debugging code
9416         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9417         {
9418                 int i;
9419                 int j;
9420                 int c;
9421                 const int *e;
9422                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9423                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9424                 {
9425                         c = e[i];
9426                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9427                         {
9428                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9429                                 {
9430                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9431                                                 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);
9432                                         break;
9433                                 }
9434                         }
9435                 }
9436         }
9437 #endif
9438         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);
9439 }
9440
9441 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9442 {
9443         // pick the closest matching water plane
9444         int planeindex, vertexindex, bestplaneindex = -1;
9445         float d, bestd;
9446         vec3_t vert;
9447         const float *v;
9448         r_waterstate_waterplane_t *p;
9449         qboolean prepared = false;
9450         bestd = 0;
9451         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9452         {
9453                 if(p->camera_entity != rsurface.texture->camera_entity)
9454                         continue;
9455                 d = 0;
9456                 if(!prepared)
9457                 {
9458                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9459                         prepared = true;
9460                         if(rsurface.batchnumvertices == 0)
9461                                 break;
9462                 }
9463                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9464                 {
9465                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9466                         d += fabs(PlaneDiff(vert, &p->plane));
9467                 }
9468                 if (bestd > d || bestplaneindex < 0)
9469                 {
9470                         bestd = d;
9471                         bestplaneindex = planeindex;
9472                 }
9473         }
9474         return bestplaneindex;
9475         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9476         // this situation though, as it might be better to render single larger
9477         // batches with useless stuff (backface culled for example) than to
9478         // render multiple smaller batches
9479 }
9480
9481 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9482 {
9483         int i;
9484         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9485         rsurface.passcolor4f_vertexbuffer = 0;
9486         rsurface.passcolor4f_bufferoffset = 0;
9487         for (i = 0;i < rsurface.batchnumvertices;i++)
9488                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9489 }
9490
9491 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9492 {
9493         int i;
9494         float f;
9495         const float *v;
9496         const float *c;
9497         float *c2;
9498         if (rsurface.passcolor4f)
9499         {
9500                 // generate color arrays
9501                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9502                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9503                 rsurface.passcolor4f_vertexbuffer = 0;
9504                 rsurface.passcolor4f_bufferoffset = 0;
9505                 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)
9506                 {
9507                         f = RSurf_FogVertex(v);
9508                         c2[0] = c[0] * f;
9509                         c2[1] = c[1] * f;
9510                         c2[2] = c[2] * f;
9511                         c2[3] = c[3];
9512                 }
9513         }
9514         else
9515         {
9516                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9517                 rsurface.passcolor4f_vertexbuffer = 0;
9518                 rsurface.passcolor4f_bufferoffset = 0;
9519                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9520                 {
9521                         f = RSurf_FogVertex(v);
9522                         c2[0] = f;
9523                         c2[1] = f;
9524                         c2[2] = f;
9525                         c2[3] = 1;
9526                 }
9527         }
9528 }
9529
9530 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9531 {
9532         int i;
9533         float f;
9534         const float *v;
9535         const float *c;
9536         float *c2;
9537         if (!rsurface.passcolor4f)
9538                 return;
9539         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9540         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9541         rsurface.passcolor4f_vertexbuffer = 0;
9542         rsurface.passcolor4f_bufferoffset = 0;
9543         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)
9544         {
9545                 f = RSurf_FogVertex(v);
9546                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9547                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9548                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9549                 c2[3] = c[3];
9550         }
9551 }
9552
9553 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9554 {
9555         int i;
9556         const float *c;
9557         float *c2;
9558         if (!rsurface.passcolor4f)
9559                 return;
9560         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9561         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9562         rsurface.passcolor4f_vertexbuffer = 0;
9563         rsurface.passcolor4f_bufferoffset = 0;
9564         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9565         {
9566                 c2[0] = c[0] * r;
9567                 c2[1] = c[1] * g;
9568                 c2[2] = c[2] * b;
9569                 c2[3] = c[3] * a;
9570         }
9571 }
9572
9573 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9574 {
9575         int i;
9576         const float *c;
9577         float *c2;
9578         if (!rsurface.passcolor4f)
9579                 return;
9580         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9581         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9582         rsurface.passcolor4f_vertexbuffer = 0;
9583         rsurface.passcolor4f_bufferoffset = 0;
9584         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9585         {
9586                 c2[0] = c[0] + r_refdef.scene.ambient;
9587                 c2[1] = c[1] + r_refdef.scene.ambient;
9588                 c2[2] = c[2] + r_refdef.scene.ambient;
9589                 c2[3] = c[3];
9590         }
9591 }
9592
9593 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9594 {
9595         // TODO: optimize
9596         rsurface.passcolor4f = NULL;
9597         rsurface.passcolor4f_vertexbuffer = 0;
9598         rsurface.passcolor4f_bufferoffset = 0;
9599         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9600         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9601         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9602         GL_Color(r, g, b, a);
9603         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9604         RSurf_DrawBatch();
9605 }
9606
9607 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9608 {
9609         // TODO: optimize applyfog && applycolor case
9610         // just apply fog if necessary, and tint the fog color array if necessary
9611         rsurface.passcolor4f = NULL;
9612         rsurface.passcolor4f_vertexbuffer = 0;
9613         rsurface.passcolor4f_bufferoffset = 0;
9614         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9615         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9616         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9617         GL_Color(r, g, b, a);
9618         RSurf_DrawBatch();
9619 }
9620
9621 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9622 {
9623         // TODO: optimize
9624         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9625         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9626         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9627         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9628         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9629         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9630         GL_Color(r, g, b, a);
9631         RSurf_DrawBatch();
9632 }
9633
9634 static void RSurf_DrawBatch_GL11_ClampColor(void)
9635 {
9636         int i;
9637         const float *c1;
9638         float *c2;
9639         if (!rsurface.passcolor4f)
9640                 return;
9641         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9642         {
9643                 c2[0] = bound(0.0f, c1[0], 1.0f);
9644                 c2[1] = bound(0.0f, c1[1], 1.0f);
9645                 c2[2] = bound(0.0f, c1[2], 1.0f);
9646                 c2[3] = bound(0.0f, c1[3], 1.0f);
9647         }
9648 }
9649
9650 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9651 {
9652         int i;
9653         float f;
9654         const float *v;
9655         const float *n;
9656         float *c;
9657         //vec3_t eyedir;
9658
9659         // fake shading
9660         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9661         rsurface.passcolor4f_vertexbuffer = 0;
9662         rsurface.passcolor4f_bufferoffset = 0;
9663         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)
9664         {
9665                 f = -DotProduct(r_refdef.view.forward, n);
9666                 f = max(0, f);
9667                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9668                 f *= r_refdef.lightmapintensity;
9669                 Vector4Set(c, f, f, f, 1);
9670         }
9671 }
9672
9673 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9674 {
9675         RSurf_DrawBatch_GL11_ApplyFakeLight();
9676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9678         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9679         GL_Color(r, g, b, a);
9680         RSurf_DrawBatch();
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9684 {
9685         int i;
9686         float f;
9687         float alpha;
9688         const float *v;
9689         const float *n;
9690         float *c;
9691         vec3_t ambientcolor;
9692         vec3_t diffusecolor;
9693         vec3_t lightdir;
9694         // TODO: optimize
9695         // model lighting
9696         VectorCopy(rsurface.modellight_lightdir, lightdir);
9697         f = 0.5f * r_refdef.lightmapintensity;
9698         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9699         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9700         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9701         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9702         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9703         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9704         alpha = *a;
9705         if (VectorLength2(diffusecolor) > 0)
9706         {
9707                 // q3-style directional shading
9708                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9709                 rsurface.passcolor4f_vertexbuffer = 0;
9710                 rsurface.passcolor4f_bufferoffset = 0;
9711                 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)
9712                 {
9713                         if ((f = DotProduct(n, lightdir)) > 0)
9714                                 VectorMA(ambientcolor, f, diffusecolor, c);
9715                         else
9716                                 VectorCopy(ambientcolor, c);
9717                         c[3] = alpha;
9718                 }
9719                 *r = 1;
9720                 *g = 1;
9721                 *b = 1;
9722                 *a = 1;
9723                 *applycolor = false;
9724         }
9725         else
9726         {
9727                 *r = ambientcolor[0];
9728                 *g = ambientcolor[1];
9729                 *b = ambientcolor[2];
9730                 rsurface.passcolor4f = NULL;
9731                 rsurface.passcolor4f_vertexbuffer = 0;
9732                 rsurface.passcolor4f_bufferoffset = 0;
9733         }
9734 }
9735
9736 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9737 {
9738         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9739         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9740         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9741         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9742         GL_Color(r, g, b, a);
9743         RSurf_DrawBatch();
9744 }
9745
9746 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9747 {
9748         int i;
9749         float f;
9750         const float *v;
9751         float *c;
9752
9753         // fake shading
9754         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9755         rsurface.passcolor4f_vertexbuffer = 0;
9756         rsurface.passcolor4f_bufferoffset = 0;
9757
9758         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9759         {
9760                 f = 1 - RSurf_FogVertex(v);
9761                 c[0] = r;
9762                 c[1] = g;
9763                 c[2] = b;
9764                 c[3] = f * a;
9765         }
9766 }
9767
9768 void RSurf_SetupDepthAndCulling(void)
9769 {
9770         // submodels are biased to avoid z-fighting with world surfaces that they
9771         // may be exactly overlapping (avoids z-fighting artifacts on certain
9772         // doors and things in Quake maps)
9773         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9774         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9775         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9776         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9777 }
9778
9779 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9780 {
9781         // transparent sky would be ridiculous
9782         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9783                 return;
9784         R_SetupShader_Generic_NoTexture(false, false);
9785         skyrenderlater = true;
9786         RSurf_SetupDepthAndCulling();
9787         GL_DepthMask(true);
9788         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9789         // skymasking on them, and Quake3 never did sky masking (unlike
9790         // software Quake and software Quake2), so disable the sky masking
9791         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9792         // and skymasking also looks very bad when noclipping outside the
9793         // level, so don't use it then either.
9794         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9795         {
9796                 R_Mesh_ResetTextureState();
9797                 if (skyrendermasked)
9798                 {
9799                         R_SetupShader_DepthOrShadow(false);
9800                         // depth-only (masking)
9801                         GL_ColorMask(0,0,0,0);
9802                         // just to make sure that braindead drivers don't draw
9803                         // anything despite that colormask...
9804                         GL_BlendFunc(GL_ZERO, GL_ONE);
9805                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9806                         if (rsurface.batchvertex3fbuffer)
9807                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9808                         else
9809                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9810                 }
9811                 else
9812                 {
9813                         R_SetupShader_Generic_NoTexture(false, false);
9814                         // fog sky
9815                         GL_BlendFunc(GL_ONE, GL_ZERO);
9816                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9817                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9818                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9819                 }
9820                 RSurf_DrawBatch();
9821                 if (skyrendermasked)
9822                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9823         }
9824         R_Mesh_ResetTextureState();
9825         GL_Color(1, 1, 1, 1);
9826 }
9827
9828 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9829 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9830 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9831 {
9832         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9833                 return;
9834         if (prepass)
9835         {
9836                 // render screenspace normalmap to texture
9837                 GL_DepthMask(true);
9838                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9839                 RSurf_DrawBatch();
9840                 return;
9841         }
9842
9843         // bind lightmap texture
9844
9845         // water/refraction/reflection/camera surfaces have to be handled specially
9846         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9847         {
9848                 int start, end, startplaneindex;
9849                 for (start = 0;start < texturenumsurfaces;start = end)
9850                 {
9851                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9852                         if(startplaneindex < 0)
9853                         {
9854                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9855                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9856                                 end = start + 1;
9857                                 continue;
9858                         }
9859                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9860                                 ;
9861                         // now that we have a batch using the same planeindex, render it
9862                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9863                         {
9864                                 // render water or distortion background
9865                                 GL_DepthMask(true);
9866                                 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);
9867                                 RSurf_DrawBatch();
9868                                 // blend surface on top
9869                                 GL_DepthMask(false);
9870                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9871                                 RSurf_DrawBatch();
9872                         }
9873                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9874                         {
9875                                 // render surface with reflection texture as input
9876                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9877                                 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);
9878                                 RSurf_DrawBatch();
9879                         }
9880                 }
9881                 return;
9882         }
9883
9884         // render surface batch normally
9885         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9886         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9887         RSurf_DrawBatch();
9888 }
9889
9890 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9891 {
9892         // OpenGL 1.3 path - anything not completely ancient
9893         qboolean applycolor;
9894         qboolean applyfog;
9895         int layerindex;
9896         const texturelayer_t *layer;
9897         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);
9898         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9899
9900         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9901         {
9902                 vec4_t layercolor;
9903                 int layertexrgbscale;
9904                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9905                 {
9906                         if (layerindex == 0)
9907                                 GL_AlphaTest(true);
9908                         else
9909                         {
9910                                 GL_AlphaTest(false);
9911                                 GL_DepthFunc(GL_EQUAL);
9912                         }
9913                 }
9914                 GL_DepthMask(layer->depthmask && writedepth);
9915                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9916                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9917                 {
9918                         layertexrgbscale = 4;
9919                         VectorScale(layer->color, 0.25f, layercolor);
9920                 }
9921                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9922                 {
9923                         layertexrgbscale = 2;
9924                         VectorScale(layer->color, 0.5f, layercolor);
9925                 }
9926                 else
9927                 {
9928                         layertexrgbscale = 1;
9929                         VectorScale(layer->color, 1.0f, layercolor);
9930                 }
9931                 layercolor[3] = layer->color[3];
9932                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9933                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9934                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9935                 switch (layer->type)
9936                 {
9937                 case TEXTURELAYERTYPE_LITTEXTURE:
9938                         // single-pass lightmapped texture with 2x rgbscale
9939                         R_Mesh_TexBind(0, r_texture_white);
9940                         R_Mesh_TexMatrix(0, NULL);
9941                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9942                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9943                         R_Mesh_TexBind(1, layer->texture);
9944                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9945                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9946                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9947                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9948                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9949                         else if (FAKELIGHT_ENABLED)
9950                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9951                         else if (rsurface.uselightmaptexture)
9952                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         else
9954                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9955                         break;
9956                 case TEXTURELAYERTYPE_TEXTURE:
9957                         // singletexture unlit texture with transparency support
9958                         R_Mesh_TexBind(0, layer->texture);
9959                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9960                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9961                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9962                         R_Mesh_TexBind(1, 0);
9963                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9964                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9965                         break;
9966                 case TEXTURELAYERTYPE_FOG:
9967                         // singletexture fogging
9968                         if (layer->texture)
9969                         {
9970                                 R_Mesh_TexBind(0, layer->texture);
9971                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9972                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9973                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9974                         }
9975                         else
9976                         {
9977                                 R_Mesh_TexBind(0, 0);
9978                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9979                         }
9980                         R_Mesh_TexBind(1, 0);
9981                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9982                         // generate a color array for the fog pass
9983                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9984                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9985                         RSurf_DrawBatch();
9986                         break;
9987                 default:
9988                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9989                 }
9990         }
9991         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9992         {
9993                 GL_DepthFunc(GL_LEQUAL);
9994                 GL_AlphaTest(false);
9995         }
9996 }
9997
9998 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9999 {
10000         // OpenGL 1.1 - crusty old voodoo path
10001         qboolean applyfog;
10002         int layerindex;
10003         const texturelayer_t *layer;
10004         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);
10005         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10006
10007         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10008         {
10009                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10010                 {
10011                         if (layerindex == 0)
10012                                 GL_AlphaTest(true);
10013                         else
10014                         {
10015                                 GL_AlphaTest(false);
10016                                 GL_DepthFunc(GL_EQUAL);
10017                         }
10018                 }
10019                 GL_DepthMask(layer->depthmask && writedepth);
10020                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10021                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10022                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10023                 switch (layer->type)
10024                 {
10025                 case TEXTURELAYERTYPE_LITTEXTURE:
10026                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10027                         {
10028                                 // two-pass lit texture with 2x rgbscale
10029                                 // first the lightmap pass
10030                                 R_Mesh_TexBind(0, r_texture_white);
10031                                 R_Mesh_TexMatrix(0, NULL);
10032                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10033                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10034                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10035                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10036                                 else if (FAKELIGHT_ENABLED)
10037                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10038                                 else if (rsurface.uselightmaptexture)
10039                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10040                                 else
10041                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10042                                 // then apply the texture to it
10043                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10044                                 R_Mesh_TexBind(0, layer->texture);
10045                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10046                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10047                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10048                                 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);
10049                         }
10050                         else
10051                         {
10052                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10053                                 R_Mesh_TexBind(0, layer->texture);
10054                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10055                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10056                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10057                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10058                                         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);
10059                                 else
10060                                         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);
10061                         }
10062                         break;
10063                 case TEXTURELAYERTYPE_TEXTURE:
10064                         // singletexture unlit texture with transparency support
10065                         R_Mesh_TexBind(0, layer->texture);
10066                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10067                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10068                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10069                         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);
10070                         break;
10071                 case TEXTURELAYERTYPE_FOG:
10072                         // singletexture fogging
10073                         if (layer->texture)
10074                         {
10075                                 R_Mesh_TexBind(0, layer->texture);
10076                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10077                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10078                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10079                         }
10080                         else
10081                         {
10082                                 R_Mesh_TexBind(0, 0);
10083                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10084                         }
10085                         // generate a color array for the fog pass
10086                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10087                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10088                         RSurf_DrawBatch();
10089                         break;
10090                 default:
10091                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10092                 }
10093         }
10094         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10095         {
10096                 GL_DepthFunc(GL_LEQUAL);
10097                 GL_AlphaTest(false);
10098         }
10099 }
10100
10101 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10102 {
10103         int vi;
10104         int j;
10105         r_vertexgeneric_t *batchvertex;
10106         float c[4];
10107
10108 //      R_Mesh_ResetTextureState();
10109         R_SetupShader_Generic_NoTexture(false, false);
10110
10111         if(rsurface.texture && rsurface.texture->currentskinframe)
10112         {
10113                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10114                 c[3] *= rsurface.texture->currentalpha;
10115         }
10116         else
10117         {
10118                 c[0] = 1;
10119                 c[1] = 0;
10120                 c[2] = 1;
10121                 c[3] = 1;
10122         }
10123
10124         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10125         {
10126                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10127                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10128                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10129         }
10130
10131         // brighten it up (as texture value 127 means "unlit")
10132         c[0] *= 2 * r_refdef.view.colorscale;
10133         c[1] *= 2 * r_refdef.view.colorscale;
10134         c[2] *= 2 * r_refdef.view.colorscale;
10135
10136         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10137                 c[3] *= r_wateralpha.value;
10138
10139         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10140         {
10141                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10142                 GL_DepthMask(false);
10143         }
10144         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10145         {
10146                 GL_BlendFunc(GL_ONE, GL_ONE);
10147                 GL_DepthMask(false);
10148         }
10149         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10150         {
10151                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10152                 GL_DepthMask(false);
10153         }
10154         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10155         {
10156                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10157                 GL_DepthMask(false);
10158         }
10159         else
10160         {
10161                 GL_BlendFunc(GL_ONE, GL_ZERO);
10162                 GL_DepthMask(writedepth);
10163         }
10164
10165         if (r_showsurfaces.integer == 3)
10166         {
10167                 rsurface.passcolor4f = NULL;
10168
10169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10170                 {
10171                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172
10173                         rsurface.passcolor4f = NULL;
10174                         rsurface.passcolor4f_vertexbuffer = 0;
10175                         rsurface.passcolor4f_bufferoffset = 0;
10176                 }
10177                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10178                 {
10179                         qboolean applycolor = true;
10180                         float one = 1.0;
10181
10182                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10183
10184                         r_refdef.lightmapintensity = 1;
10185                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10186                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10187                 }
10188                 else if (FAKELIGHT_ENABLED)
10189                 {
10190                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10191
10192                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10193                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10194                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10195                 }
10196                 else
10197                 {
10198                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10199
10200                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10201                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10202                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10203                 }
10204
10205                 if(!rsurface.passcolor4f)
10206                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10207
10208                 RSurf_DrawBatch_GL11_ApplyAmbient();
10209                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10210                 if(r_refdef.fogenabled)
10211                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10212                 RSurf_DrawBatch_GL11_ClampColor();
10213
10214                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10215                 R_SetupShader_Generic_NoTexture(false, false);
10216                 RSurf_DrawBatch();
10217         }
10218         else if (!r_refdef.view.showdebug)
10219         {
10220                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10221                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10222                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10223                 {
10224                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10225                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10226                 }
10227                 R_Mesh_PrepareVertices_Generic_Unlock();
10228                 RSurf_DrawBatch();
10229         }
10230         else if (r_showsurfaces.integer == 4)
10231         {
10232                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10233                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10234                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10235                 {
10236                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10237                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10238                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10239                 }
10240                 R_Mesh_PrepareVertices_Generic_Unlock();
10241                 RSurf_DrawBatch();
10242         }
10243         else if (r_showsurfaces.integer == 2)
10244         {
10245                 const int *e;
10246                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10247                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10248                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10249                 {
10250                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10251                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10252                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10253                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10254                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10255                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10256                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10257                 }
10258                 R_Mesh_PrepareVertices_Generic_Unlock();
10259                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10260         }
10261         else
10262         {
10263                 int texturesurfaceindex;
10264                 int k;
10265                 const msurface_t *surface;
10266                 float surfacecolor4f[4];
10267                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10268                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10269                 vi = 0;
10270                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10271                 {
10272                         surface = texturesurfacelist[texturesurfaceindex];
10273                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10274                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10275                         for (j = 0;j < surface->num_vertices;j++)
10276                         {
10277                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10278                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10279                                 vi++;
10280                         }
10281                 }
10282                 R_Mesh_PrepareVertices_Generic_Unlock();
10283                 RSurf_DrawBatch();
10284         }
10285 }
10286
10287 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10288 {
10289         CHECKGLERROR
10290         RSurf_SetupDepthAndCulling();
10291         if (r_showsurfaces.integer)
10292         {
10293                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10294                 return;
10295         }
10296         switch (vid.renderpath)
10297         {
10298         case RENDERPATH_GL20:
10299         case RENDERPATH_D3D9:
10300         case RENDERPATH_D3D10:
10301         case RENDERPATH_D3D11:
10302         case RENDERPATH_SOFT:
10303         case RENDERPATH_GLES2:
10304                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10305                 break;
10306         case RENDERPATH_GL13:
10307         case RENDERPATH_GLES1:
10308                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10309                 break;
10310         case RENDERPATH_GL11:
10311                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10312                 break;
10313         }
10314         CHECKGLERROR
10315 }
10316
10317 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10318 {
10319         CHECKGLERROR
10320         RSurf_SetupDepthAndCulling();
10321         if (r_showsurfaces.integer)
10322         {
10323                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10324                 return;
10325         }
10326         switch (vid.renderpath)
10327         {
10328         case RENDERPATH_GL20:
10329         case RENDERPATH_D3D9:
10330         case RENDERPATH_D3D10:
10331         case RENDERPATH_D3D11:
10332         case RENDERPATH_SOFT:
10333         case RENDERPATH_GLES2:
10334                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10335                 break;
10336         case RENDERPATH_GL13:
10337         case RENDERPATH_GLES1:
10338                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10339                 break;
10340         case RENDERPATH_GL11:
10341                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10342                 break;
10343         }
10344         CHECKGLERROR
10345 }
10346
10347 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10348 {
10349         int i, j;
10350         int texturenumsurfaces, endsurface;
10351         texture_t *texture;
10352         const msurface_t *surface;
10353         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10354
10355         // if the model is static it doesn't matter what value we give for
10356         // wantnormals and wanttangents, so this logic uses only rules applicable
10357         // to a model, knowing that they are meaningless otherwise
10358         if (ent == r_refdef.scene.worldentity)
10359                 RSurf_ActiveWorldEntity();
10360         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10361                 RSurf_ActiveModelEntity(ent, false, false, false);
10362         else
10363         {
10364                 switch (vid.renderpath)
10365                 {
10366                 case RENDERPATH_GL20:
10367                 case RENDERPATH_D3D9:
10368                 case RENDERPATH_D3D10:
10369                 case RENDERPATH_D3D11:
10370                 case RENDERPATH_SOFT:
10371                 case RENDERPATH_GLES2:
10372                         RSurf_ActiveModelEntity(ent, true, true, false);
10373                         break;
10374                 case RENDERPATH_GL11:
10375                 case RENDERPATH_GL13:
10376                 case RENDERPATH_GLES1:
10377                         RSurf_ActiveModelEntity(ent, true, false, false);
10378                         break;
10379                 }
10380         }
10381
10382         if (r_transparentdepthmasking.integer)
10383         {
10384                 qboolean setup = false;
10385                 for (i = 0;i < numsurfaces;i = j)
10386                 {
10387                         j = i + 1;
10388                         surface = rsurface.modelsurfaces + surfacelist[i];
10389                         texture = surface->texture;
10390                         rsurface.texture = R_GetCurrentTexture(texture);
10391                         rsurface.lightmaptexture = NULL;
10392                         rsurface.deluxemaptexture = NULL;
10393                         rsurface.uselightmaptexture = false;
10394                         // scan ahead until we find a different texture
10395                         endsurface = min(i + 1024, numsurfaces);
10396                         texturenumsurfaces = 0;
10397                         texturesurfacelist[texturenumsurfaces++] = surface;
10398                         for (;j < endsurface;j++)
10399                         {
10400                                 surface = rsurface.modelsurfaces + surfacelist[j];
10401                                 if (texture != surface->texture)
10402                                         break;
10403                                 texturesurfacelist[texturenumsurfaces++] = surface;
10404                         }
10405                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10406                                 continue;
10407                         // render the range of surfaces as depth
10408                         if (!setup)
10409                         {
10410                                 setup = true;
10411                                 GL_ColorMask(0,0,0,0);
10412                                 GL_Color(1,1,1,1);
10413                                 GL_DepthTest(true);
10414                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10415                                 GL_DepthMask(true);
10416 //                              R_Mesh_ResetTextureState();
10417                                 R_SetupShader_DepthOrShadow(false);
10418                         }
10419                         RSurf_SetupDepthAndCulling();
10420                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10421                         if (rsurface.batchvertex3fbuffer)
10422                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10423                         else
10424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10425                         RSurf_DrawBatch();
10426                 }
10427                 if (setup)
10428                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10429         }
10430
10431         for (i = 0;i < numsurfaces;i = j)
10432         {
10433                 j = i + 1;
10434                 surface = rsurface.modelsurfaces + surfacelist[i];
10435                 texture = surface->texture;
10436                 rsurface.texture = R_GetCurrentTexture(texture);
10437                 // scan ahead until we find a different texture
10438                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10439                 texturenumsurfaces = 0;
10440                 texturesurfacelist[texturenumsurfaces++] = surface;
10441                 if(FAKELIGHT_ENABLED)
10442                 {
10443                         rsurface.lightmaptexture = NULL;
10444                         rsurface.deluxemaptexture = NULL;
10445                         rsurface.uselightmaptexture = false;
10446                         for (;j < endsurface;j++)
10447                         {
10448                                 surface = rsurface.modelsurfaces + surfacelist[j];
10449                                 if (texture != surface->texture)
10450                                         break;
10451                                 texturesurfacelist[texturenumsurfaces++] = surface;
10452                         }
10453                 }
10454                 else
10455                 {
10456                         rsurface.lightmaptexture = surface->lightmaptexture;
10457                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10458                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10459                         for (;j < endsurface;j++)
10460                         {
10461                                 surface = rsurface.modelsurfaces + surfacelist[j];
10462                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10463                                         break;
10464                                 texturesurfacelist[texturenumsurfaces++] = surface;
10465                         }
10466                 }
10467                 // render the range of surfaces
10468                 if (ent == r_refdef.scene.worldentity)
10469                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10470                 else
10471                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10472         }
10473         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10474 }
10475
10476 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10477 {
10478         // transparent surfaces get pushed off into the transparent queue
10479         int surfacelistindex;
10480         const msurface_t *surface;
10481         vec3_t tempcenter, center;
10482         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10483         {
10484                 surface = texturesurfacelist[surfacelistindex];
10485                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10486                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10487                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10488                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10489                 if (queueentity->transparent_offset) // transparent offset
10490                 {
10491                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10492                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10493                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10494                 }
10495                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10496         }
10497 }
10498
10499 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10500 {
10501         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10502                 return;
10503         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10504                 return;
10505         RSurf_SetupDepthAndCulling();
10506         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10507         if (rsurface.batchvertex3fbuffer)
10508                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10509         else
10510                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10511         RSurf_DrawBatch();
10512 }
10513
10514 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10515 {
10516         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10517         CHECKGLERROR
10518         if (depthonly)
10519                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10520         else if (prepass)
10521         {
10522                 if (!rsurface.texture->currentnumlayers)
10523                         return;
10524                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10525                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10526                 else
10527                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10528         }
10529         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10530                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10531         else if (!rsurface.texture->currentnumlayers)
10532                 return;
10533         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10534         {
10535                 // in the deferred case, transparent surfaces were queued during prepass
10536                 if (!r_shadow_usingdeferredprepass)
10537                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10538         }
10539         else
10540         {
10541                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10542                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10543         }
10544         CHECKGLERROR
10545 }
10546
10547 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10548 {
10549         int i, j;
10550         texture_t *texture;
10551         R_FrameData_SetMark();
10552         // break the surface list down into batches by texture and use of lightmapping
10553         for (i = 0;i < numsurfaces;i = j)
10554         {
10555                 j = i + 1;
10556                 // texture is the base texture pointer, rsurface.texture is the
10557                 // current frame/skin the texture is directing us to use (for example
10558                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10559                 // use skin 1 instead)
10560                 texture = surfacelist[i]->texture;
10561                 rsurface.texture = R_GetCurrentTexture(texture);
10562                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10563                 {
10564                         // if this texture is not the kind we want, skip ahead to the next one
10565                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10566                                 ;
10567                         continue;
10568                 }
10569                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10570                 {
10571                         rsurface.lightmaptexture = NULL;
10572                         rsurface.deluxemaptexture = NULL;
10573                         rsurface.uselightmaptexture = false;
10574                         // simply scan ahead until we find a different texture or lightmap state
10575                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10576                                 ;
10577                 }
10578                 else
10579                 {
10580                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10581                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10582                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10583                         // simply scan ahead until we find a different texture or lightmap state
10584                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10585                                 ;
10586                 }
10587                 // render the range of surfaces
10588                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10589         }
10590         R_FrameData_ReturnToMark();
10591 }
10592
10593 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10594 {
10595         CHECKGLERROR
10596         if (depthonly)
10597                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10598         else if (prepass)
10599         {
10600                 if (!rsurface.texture->currentnumlayers)
10601                         return;
10602                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10603                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10604                 else
10605                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10606         }
10607         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10608                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10609         else if (!rsurface.texture->currentnumlayers)
10610                 return;
10611         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10612         {
10613                 // in the deferred case, transparent surfaces were queued during prepass
10614                 if (!r_shadow_usingdeferredprepass)
10615                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10616         }
10617         else
10618         {
10619                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10620                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10621         }
10622         CHECKGLERROR
10623 }
10624
10625 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10626 {
10627         int i, j;
10628         texture_t *texture;
10629         R_FrameData_SetMark();
10630         // break the surface list down into batches by texture and use of lightmapping
10631         for (i = 0;i < numsurfaces;i = j)
10632         {
10633                 j = i + 1;
10634                 // texture is the base texture pointer, rsurface.texture is the
10635                 // current frame/skin the texture is directing us to use (for example
10636                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10637                 // use skin 1 instead)
10638                 texture = surfacelist[i]->texture;
10639                 rsurface.texture = R_GetCurrentTexture(texture);
10640                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10641                 {
10642                         // if this texture is not the kind we want, skip ahead to the next one
10643                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10644                                 ;
10645                         continue;
10646                 }
10647                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10648                 {
10649                         rsurface.lightmaptexture = NULL;
10650                         rsurface.deluxemaptexture = NULL;
10651                         rsurface.uselightmaptexture = false;
10652                         // simply scan ahead until we find a different texture or lightmap state
10653                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10654                                 ;
10655                 }
10656                 else
10657                 {
10658                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10659                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10660                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10661                         // simply scan ahead until we find a different texture or lightmap state
10662                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10663                                 ;
10664                 }
10665                 // render the range of surfaces
10666                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10667         }
10668         R_FrameData_ReturnToMark();
10669 }
10670
10671 float locboxvertex3f[6*4*3] =
10672 {
10673         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10674         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10675         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10676         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10677         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10678         1,0,0, 0,0,0, 0,1,0, 1,1,0
10679 };
10680
10681 unsigned short locboxelements[6*2*3] =
10682 {
10683          0, 1, 2, 0, 2, 3,
10684          4, 5, 6, 4, 6, 7,
10685          8, 9,10, 8,10,11,
10686         12,13,14, 12,14,15,
10687         16,17,18, 16,18,19,
10688         20,21,22, 20,22,23
10689 };
10690
10691 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10692 {
10693         int i, j;
10694         cl_locnode_t *loc = (cl_locnode_t *)ent;
10695         vec3_t mins, size;
10696         float vertex3f[6*4*3];
10697         CHECKGLERROR
10698         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10699         GL_DepthMask(false);
10700         GL_DepthRange(0, 1);
10701         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10702         GL_DepthTest(true);
10703         GL_CullFace(GL_NONE);
10704         R_EntityMatrix(&identitymatrix);
10705
10706 //      R_Mesh_ResetTextureState();
10707
10708         i = surfacelist[0];
10709         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10710                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10711                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10712                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10713
10714         if (VectorCompare(loc->mins, loc->maxs))
10715         {
10716                 VectorSet(size, 2, 2, 2);
10717                 VectorMA(loc->mins, -0.5f, size, mins);
10718         }
10719         else
10720         {
10721                 VectorCopy(loc->mins, mins);
10722                 VectorSubtract(loc->maxs, loc->mins, size);
10723         }
10724
10725         for (i = 0;i < 6*4*3;)
10726                 for (j = 0;j < 3;j++, i++)
10727                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10728
10729         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10730         R_SetupShader_Generic_NoTexture(false, false);
10731         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10732 }
10733
10734 void R_DrawLocs(void)
10735 {
10736         int index;
10737         cl_locnode_t *loc, *nearestloc;
10738         vec3_t center;
10739         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10740         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10741         {
10742                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10743                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10744         }
10745 }
10746
10747 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10748 {
10749         if (decalsystem->decals)
10750                 Mem_Free(decalsystem->decals);
10751         memset(decalsystem, 0, sizeof(*decalsystem));
10752 }
10753
10754 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)
10755 {
10756         tridecal_t *decal;
10757         tridecal_t *decals;
10758         int i;
10759
10760         // expand or initialize the system
10761         if (decalsystem->maxdecals <= decalsystem->numdecals)
10762         {
10763                 decalsystem_t old = *decalsystem;
10764                 qboolean useshortelements;
10765                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10766                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10767                 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)));
10768                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10769                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10770                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10771                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10772                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10773                 if (decalsystem->numdecals)
10774                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10775                 if (old.decals)
10776                         Mem_Free(old.decals);
10777                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10778                         decalsystem->element3i[i] = i;
10779                 if (useshortelements)
10780                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10781                                 decalsystem->element3s[i] = i;
10782         }
10783
10784         // grab a decal and search for another free slot for the next one
10785         decals = decalsystem->decals;
10786         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10787         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10788                 ;
10789         decalsystem->freedecal = i;
10790         if (decalsystem->numdecals <= i)
10791                 decalsystem->numdecals = i + 1;
10792
10793         // initialize the decal
10794         decal->lived = 0;
10795         decal->triangleindex = triangleindex;
10796         decal->surfaceindex = surfaceindex;
10797         decal->decalsequence = decalsequence;
10798         decal->color4f[0][0] = c0[0];
10799         decal->color4f[0][1] = c0[1];
10800         decal->color4f[0][2] = c0[2];
10801         decal->color4f[0][3] = 1;
10802         decal->color4f[1][0] = c1[0];
10803         decal->color4f[1][1] = c1[1];
10804         decal->color4f[1][2] = c1[2];
10805         decal->color4f[1][3] = 1;
10806         decal->color4f[2][0] = c2[0];
10807         decal->color4f[2][1] = c2[1];
10808         decal->color4f[2][2] = c2[2];
10809         decal->color4f[2][3] = 1;
10810         decal->vertex3f[0][0] = v0[0];
10811         decal->vertex3f[0][1] = v0[1];
10812         decal->vertex3f[0][2] = v0[2];
10813         decal->vertex3f[1][0] = v1[0];
10814         decal->vertex3f[1][1] = v1[1];
10815         decal->vertex3f[1][2] = v1[2];
10816         decal->vertex3f[2][0] = v2[0];
10817         decal->vertex3f[2][1] = v2[1];
10818         decal->vertex3f[2][2] = v2[2];
10819         decal->texcoord2f[0][0] = t0[0];
10820         decal->texcoord2f[0][1] = t0[1];
10821         decal->texcoord2f[1][0] = t1[0];
10822         decal->texcoord2f[1][1] = t1[1];
10823         decal->texcoord2f[2][0] = t2[0];
10824         decal->texcoord2f[2][1] = t2[1];
10825         TriangleNormal(v0, v1, v2, decal->plane);
10826         VectorNormalize(decal->plane);
10827         decal->plane[3] = DotProduct(v0, decal->plane);
10828 }
10829
10830 extern cvar_t cl_decals_bias;
10831 extern cvar_t cl_decals_models;
10832 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10833 // baseparms, parms, temps
10834 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)
10835 {
10836         int cornerindex;
10837         int index;
10838         float v[9][3];
10839         const float *vertex3f;
10840         const float *normal3f;
10841         int numpoints;
10842         float points[2][9][3];
10843         float temp[3];
10844         float tc[9][2];
10845         float f;
10846         float c[9][4];
10847         const int *e;
10848
10849         e = rsurface.modelelement3i + 3*triangleindex;
10850
10851         vertex3f = rsurface.modelvertex3f;
10852         normal3f = rsurface.modelnormal3f;
10853
10854         if (normal3f)
10855         {
10856                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10857                 {
10858                         index = 3*e[cornerindex];
10859                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10860                 }
10861         }
10862         else
10863         {
10864                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10865                 {
10866                         index = 3*e[cornerindex];
10867                         VectorCopy(vertex3f + index, v[cornerindex]);
10868                 }
10869         }
10870
10871         // cull backfaces
10872         //TriangleNormal(v[0], v[1], v[2], normal);
10873         //if (DotProduct(normal, localnormal) < 0.0f)
10874         //      continue;
10875         // clip by each of the box planes formed from the projection matrix
10876         // if anything survives, we emit the decal
10877         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]);
10878         if (numpoints < 3)
10879                 return;
10880         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]);
10881         if (numpoints < 3)
10882                 return;
10883         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]);
10884         if (numpoints < 3)
10885                 return;
10886         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]);
10887         if (numpoints < 3)
10888                 return;
10889         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]);
10890         if (numpoints < 3)
10891                 return;
10892         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]);
10893         if (numpoints < 3)
10894                 return;
10895         // some part of the triangle survived, so we have to accept it...
10896         if (dynamic)
10897         {
10898                 // dynamic always uses the original triangle
10899                 numpoints = 3;
10900                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10901                 {
10902                         index = 3*e[cornerindex];
10903                         VectorCopy(vertex3f + index, v[cornerindex]);
10904                 }
10905         }
10906         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10907         {
10908                 // convert vertex positions to texcoords
10909                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10910                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10911                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10912                 // calculate distance fade from the projection origin
10913                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10914                 f = bound(0.0f, f, 1.0f);
10915                 c[cornerindex][0] = r * f;
10916                 c[cornerindex][1] = g * f;
10917                 c[cornerindex][2] = b * f;
10918                 c[cornerindex][3] = 1.0f;
10919                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10920         }
10921         if (dynamic)
10922                 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);
10923         else
10924                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10925                         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);
10926 }
10927 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)
10928 {
10929         matrix4x4_t projection;
10930         decalsystem_t *decalsystem;
10931         qboolean dynamic;
10932         dp_model_t *model;
10933         const msurface_t *surface;
10934         const msurface_t *surfaces;
10935         const int *surfacelist;
10936         const texture_t *texture;
10937         int numtriangles;
10938         int numsurfacelist;
10939         int surfacelistindex;
10940         int surfaceindex;
10941         int triangleindex;
10942         float localorigin[3];
10943         float localnormal[3];
10944         float localmins[3];
10945         float localmaxs[3];
10946         float localsize;
10947         //float normal[3];
10948         float planes[6][4];
10949         float angles[3];
10950         bih_t *bih;
10951         int bih_triangles_count;
10952         int bih_triangles[256];
10953         int bih_surfaces[256];
10954
10955         decalsystem = &ent->decalsystem;
10956         model = ent->model;
10957         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10958         {
10959                 R_DecalSystem_Reset(&ent->decalsystem);
10960                 return;
10961         }
10962
10963         if (!model->brush.data_leafs && !cl_decals_models.integer)
10964         {
10965                 if (decalsystem->model)
10966                         R_DecalSystem_Reset(decalsystem);
10967                 return;
10968         }
10969
10970         if (decalsystem->model != model)
10971                 R_DecalSystem_Reset(decalsystem);
10972         decalsystem->model = model;
10973
10974         RSurf_ActiveModelEntity(ent, true, false, false);
10975
10976         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10977         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10978         VectorNormalize(localnormal);
10979         localsize = worldsize*rsurface.inversematrixscale;
10980         localmins[0] = localorigin[0] - localsize;
10981         localmins[1] = localorigin[1] - localsize;
10982         localmins[2] = localorigin[2] - localsize;
10983         localmaxs[0] = localorigin[0] + localsize;
10984         localmaxs[1] = localorigin[1] + localsize;
10985         localmaxs[2] = localorigin[2] + localsize;
10986
10987         //VectorCopy(localnormal, planes[4]);
10988         //VectorVectors(planes[4], planes[2], planes[0]);
10989         AnglesFromVectors(angles, localnormal, NULL, false);
10990         AngleVectors(angles, planes[0], planes[2], planes[4]);
10991         VectorNegate(planes[0], planes[1]);
10992         VectorNegate(planes[2], planes[3]);
10993         VectorNegate(planes[4], planes[5]);
10994         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10995         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10996         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10997         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10998         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10999         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11000
11001 #if 1
11002 // works
11003 {
11004         matrix4x4_t forwardprojection;
11005         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11006         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11007 }
11008 #else
11009 // broken
11010 {
11011         float projectionvector[4][3];
11012         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11013         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11014         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11015         projectionvector[0][0] = planes[0][0] * ilocalsize;
11016         projectionvector[0][1] = planes[1][0] * ilocalsize;
11017         projectionvector[0][2] = planes[2][0] * ilocalsize;
11018         projectionvector[1][0] = planes[0][1] * ilocalsize;
11019         projectionvector[1][1] = planes[1][1] * ilocalsize;
11020         projectionvector[1][2] = planes[2][1] * ilocalsize;
11021         projectionvector[2][0] = planes[0][2] * ilocalsize;
11022         projectionvector[2][1] = planes[1][2] * ilocalsize;
11023         projectionvector[2][2] = planes[2][2] * ilocalsize;
11024         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11025         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11026         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11027         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11028 }
11029 #endif
11030
11031         dynamic = model->surfmesh.isanimated;
11032         numsurfacelist = model->nummodelsurfaces;
11033         surfacelist = model->sortedmodelsurfaces;
11034         surfaces = model->data_surfaces;
11035
11036         bih = NULL;
11037         bih_triangles_count = -1;
11038         if(!dynamic)
11039         {
11040                 if(model->render_bih.numleafs)
11041                         bih = &model->render_bih;
11042                 else if(model->collision_bih.numleafs)
11043                         bih = &model->collision_bih;
11044         }
11045         if(bih)
11046                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11047         if(bih_triangles_count == 0)
11048                 return;
11049         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11050                 return;
11051         if(bih_triangles_count > 0)
11052         {
11053                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11054                 {
11055                         surfaceindex = bih_surfaces[triangleindex];
11056                         surface = surfaces + surfaceindex;
11057                         texture = surface->texture;
11058                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11059                                 continue;
11060                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11061                                 continue;
11062                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11063                 }
11064         }
11065         else
11066         {
11067                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11068                 {
11069                         surfaceindex = surfacelist[surfacelistindex];
11070                         surface = surfaces + surfaceindex;
11071                         // check cull box first because it rejects more than any other check
11072                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11073                                 continue;
11074                         // skip transparent surfaces
11075                         texture = surface->texture;
11076                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11077                                 continue;
11078                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11079                                 continue;
11080                         numtriangles = surface->num_triangles;
11081                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11082                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11083                 }
11084         }
11085 }
11086
11087 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11088 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)
11089 {
11090         int renderentityindex;
11091         float worldmins[3];
11092         float worldmaxs[3];
11093         entity_render_t *ent;
11094
11095         if (!cl_decals_newsystem.integer)
11096                 return;
11097
11098         worldmins[0] = worldorigin[0] - worldsize;
11099         worldmins[1] = worldorigin[1] - worldsize;
11100         worldmins[2] = worldorigin[2] - worldsize;
11101         worldmaxs[0] = worldorigin[0] + worldsize;
11102         worldmaxs[1] = worldorigin[1] + worldsize;
11103         worldmaxs[2] = worldorigin[2] + worldsize;
11104
11105         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11106
11107         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11108         {
11109                 ent = r_refdef.scene.entities[renderentityindex];
11110                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11111                         continue;
11112
11113                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11114         }
11115 }
11116
11117 typedef struct r_decalsystem_splatqueue_s
11118 {
11119         vec3_t worldorigin;
11120         vec3_t worldnormal;
11121         float color[4];
11122         float tcrange[4];
11123         float worldsize;
11124         int decalsequence;
11125 }
11126 r_decalsystem_splatqueue_t;
11127
11128 int r_decalsystem_numqueued = 0;
11129 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11130
11131 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)
11132 {
11133         r_decalsystem_splatqueue_t *queue;
11134
11135         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11136                 return;
11137
11138         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11139         VectorCopy(worldorigin, queue->worldorigin);
11140         VectorCopy(worldnormal, queue->worldnormal);
11141         Vector4Set(queue->color, r, g, b, a);
11142         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11143         queue->worldsize = worldsize;
11144         queue->decalsequence = cl.decalsequence++;
11145 }
11146
11147 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11148 {
11149         int i;
11150         r_decalsystem_splatqueue_t *queue;
11151
11152         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11153                 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);
11154         r_decalsystem_numqueued = 0;
11155 }
11156
11157 extern cvar_t cl_decals_max;
11158 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11159 {
11160         int i;
11161         decalsystem_t *decalsystem = &ent->decalsystem;
11162         int numdecals;
11163         int killsequence;
11164         tridecal_t *decal;
11165         float frametime;
11166         float lifetime;
11167
11168         if (!decalsystem->numdecals)
11169                 return;
11170
11171         if (r_showsurfaces.integer)
11172                 return;
11173
11174         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11175         {
11176                 R_DecalSystem_Reset(decalsystem);
11177                 return;
11178         }
11179
11180         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11181         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11182
11183         if (decalsystem->lastupdatetime)
11184                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11185         else
11186                 frametime = 0;
11187         decalsystem->lastupdatetime = r_refdef.scene.time;
11188         decal = decalsystem->decals;
11189         numdecals = decalsystem->numdecals;
11190
11191         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11192         {
11193                 if (decal->color4f[0][3])
11194                 {
11195                         decal->lived += frametime;
11196                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11197                         {
11198                                 memset(decal, 0, sizeof(*decal));
11199                                 if (decalsystem->freedecal > i)
11200                                         decalsystem->freedecal = i;
11201                         }
11202                 }
11203         }
11204         decal = decalsystem->decals;
11205         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11206                 numdecals--;
11207
11208         // collapse the array by shuffling the tail decals into the gaps
11209         for (;;)
11210         {
11211                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11212                         decalsystem->freedecal++;
11213                 if (decalsystem->freedecal == numdecals)
11214                         break;
11215                 decal[decalsystem->freedecal] = decal[--numdecals];
11216         }
11217
11218         decalsystem->numdecals = numdecals;
11219
11220         if (numdecals <= 0)
11221         {
11222                 // if there are no decals left, reset decalsystem
11223                 R_DecalSystem_Reset(decalsystem);
11224         }
11225 }
11226
11227 extern skinframe_t *decalskinframe;
11228 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11229 {
11230         int i;
11231         decalsystem_t *decalsystem = &ent->decalsystem;
11232         int numdecals;
11233         tridecal_t *decal;
11234         float faderate;
11235         float alpha;
11236         float *v3f;
11237         float *c4f;
11238         float *t2f;
11239         const int *e;
11240         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11241         int numtris = 0;
11242
11243         numdecals = decalsystem->numdecals;
11244         if (!numdecals)
11245                 return;
11246
11247         if (r_showsurfaces.integer)
11248                 return;
11249
11250         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11251         {
11252                 R_DecalSystem_Reset(decalsystem);
11253                 return;
11254         }
11255
11256         // if the model is static it doesn't matter what value we give for
11257         // wantnormals and wanttangents, so this logic uses only rules applicable
11258         // to a model, knowing that they are meaningless otherwise
11259         if (ent == r_refdef.scene.worldentity)
11260                 RSurf_ActiveWorldEntity();
11261         else
11262                 RSurf_ActiveModelEntity(ent, false, false, false);
11263
11264         decalsystem->lastupdatetime = r_refdef.scene.time;
11265         decal = decalsystem->decals;
11266
11267         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11268
11269         // update vertex positions for animated models
11270         v3f = decalsystem->vertex3f;
11271         c4f = decalsystem->color4f;
11272         t2f = decalsystem->texcoord2f;
11273         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11274         {
11275                 if (!decal->color4f[0][3])
11276                         continue;
11277
11278                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11279                         continue;
11280
11281                 // skip backfaces
11282                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11283                         continue;
11284
11285                 // update color values for fading decals
11286                 if (decal->lived >= cl_decals_time.value)
11287                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11288                 else
11289                         alpha = 1.0f;
11290
11291                 c4f[ 0] = decal->color4f[0][0] * alpha;
11292                 c4f[ 1] = decal->color4f[0][1] * alpha;
11293                 c4f[ 2] = decal->color4f[0][2] * alpha;
11294                 c4f[ 3] = 1;
11295                 c4f[ 4] = decal->color4f[1][0] * alpha;
11296                 c4f[ 5] = decal->color4f[1][1] * alpha;
11297                 c4f[ 6] = decal->color4f[1][2] * alpha;
11298                 c4f[ 7] = 1;
11299                 c4f[ 8] = decal->color4f[2][0] * alpha;
11300                 c4f[ 9] = decal->color4f[2][1] * alpha;
11301                 c4f[10] = decal->color4f[2][2] * alpha;
11302                 c4f[11] = 1;
11303
11304                 t2f[0] = decal->texcoord2f[0][0];
11305                 t2f[1] = decal->texcoord2f[0][1];
11306                 t2f[2] = decal->texcoord2f[1][0];
11307                 t2f[3] = decal->texcoord2f[1][1];
11308                 t2f[4] = decal->texcoord2f[2][0];
11309                 t2f[5] = decal->texcoord2f[2][1];
11310
11311                 // update vertex positions for animated models
11312                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11313                 {
11314                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11315                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11316                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11317                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11318                 }
11319                 else
11320                 {
11321                         VectorCopy(decal->vertex3f[0], v3f);
11322                         VectorCopy(decal->vertex3f[1], v3f + 3);
11323                         VectorCopy(decal->vertex3f[2], v3f + 6);
11324                 }
11325
11326                 if (r_refdef.fogenabled)
11327                 {
11328                         alpha = RSurf_FogVertex(v3f);
11329                         VectorScale(c4f, alpha, c4f);
11330                         alpha = RSurf_FogVertex(v3f + 3);
11331                         VectorScale(c4f + 4, alpha, c4f + 4);
11332                         alpha = RSurf_FogVertex(v3f + 6);
11333                         VectorScale(c4f + 8, alpha, c4f + 8);
11334                 }
11335
11336                 v3f += 9;
11337                 c4f += 12;
11338                 t2f += 6;
11339                 numtris++;
11340         }
11341
11342         if (numtris > 0)
11343         {
11344                 r_refdef.stats.drawndecals += numtris;
11345
11346                 // now render the decals all at once
11347                 // (this assumes they all use one particle font texture!)
11348                 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);
11349 //              R_Mesh_ResetTextureState();
11350                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11351                 GL_DepthMask(false);
11352                 GL_DepthRange(0, 1);
11353                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11354                 GL_DepthTest(true);
11355                 GL_CullFace(GL_NONE);
11356                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11357                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11358                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11359         }
11360 }
11361
11362 static void R_DrawModelDecals(void)
11363 {
11364         int i, numdecals;
11365
11366         // fade faster when there are too many decals
11367         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11368         for (i = 0;i < r_refdef.scene.numentities;i++)
11369                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11370
11371         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11372         for (i = 0;i < r_refdef.scene.numentities;i++)
11373                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11374                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11375
11376         R_DecalSystem_ApplySplatEntitiesQueue();
11377
11378         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11379         for (i = 0;i < r_refdef.scene.numentities;i++)
11380                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11381
11382         r_refdef.stats.totaldecals += numdecals;
11383
11384         if (r_showsurfaces.integer)
11385                 return;
11386
11387         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11388
11389         for (i = 0;i < r_refdef.scene.numentities;i++)
11390         {
11391                 if (!r_refdef.viewcache.entityvisible[i])
11392                         continue;
11393                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11394                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11395         }
11396 }
11397
11398 extern cvar_t mod_collision_bih;
11399 void R_DrawDebugModel(void)
11400 {
11401         entity_render_t *ent = rsurface.entity;
11402         int i, j, k, l, flagsmask;
11403         const msurface_t *surface;
11404         dp_model_t *model = ent->model;
11405         vec3_t v;
11406
11407         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11408                 return;
11409
11410         if (r_showoverdraw.value > 0)
11411         {
11412                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11413                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11414                 R_SetupShader_Generic_NoTexture(false, false);
11415                 GL_DepthTest(false);
11416                 GL_DepthMask(false);
11417                 GL_DepthRange(0, 1);
11418                 GL_BlendFunc(GL_ONE, GL_ONE);
11419                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11420                 {
11421                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11422                                 continue;
11423                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11424                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11425                         {
11426                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11427                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11428                                 if (!rsurface.texture->currentlayers->depthmask)
11429                                         GL_Color(c, 0, 0, 1.0f);
11430                                 else if (ent == r_refdef.scene.worldentity)
11431                                         GL_Color(c, c, c, 1.0f);
11432                                 else
11433                                         GL_Color(0, c, 0, 1.0f);
11434                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11435                                 RSurf_DrawBatch();
11436                         }
11437                 }
11438                 rsurface.texture = NULL;
11439         }
11440
11441         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11442
11443 //      R_Mesh_ResetTextureState();
11444         R_SetupShader_Generic_NoTexture(false, false);
11445         GL_DepthRange(0, 1);
11446         GL_DepthTest(!r_showdisabledepthtest.integer);
11447         GL_DepthMask(false);
11448         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11449
11450         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11451         {
11452                 int triangleindex;
11453                 int bihleafindex;
11454                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11455                 const q3mbrush_t *brush;
11456                 const bih_t *bih = &model->collision_bih;
11457                 const bih_leaf_t *bihleaf;
11458                 float vertex3f[3][3];
11459                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11460                 cullbox = false;
11461                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11462                 {
11463                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11464                                 continue;
11465                         switch (bihleaf->type)
11466                         {
11467                         case BIH_BRUSH:
11468                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11469                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11470                                 {
11471                                         GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11472                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11473                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11474                                 }
11475                                 break;
11476                         case BIH_COLLISIONTRIANGLE:
11477                                 triangleindex = bihleaf->itemindex;
11478                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11479                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11480                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11481                                 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);
11482                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11483                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11484                                 break;
11485                         case BIH_RENDERTRIANGLE:
11486                                 triangleindex = bihleaf->itemindex;
11487                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11488                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11489                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11490                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
11491                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11492                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11493                                 break;
11494                         }
11495                 }
11496         }
11497
11498         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11499
11500 #ifndef USE_GLES2
11501         if (r_showtris.integer && qglPolygonMode)
11502         {
11503                 if (r_showdisabledepthtest.integer)
11504                 {
11505                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11506                         GL_DepthMask(false);
11507                 }
11508                 else
11509                 {
11510                         GL_BlendFunc(GL_ONE, GL_ZERO);
11511                         GL_DepthMask(true);
11512                 }
11513                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11514                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11515                 {
11516                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11517                                 continue;
11518                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11519                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11520                         {
11521                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11522                                 if (!rsurface.texture->currentlayers->depthmask)
11523                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11524                                 else if (ent == r_refdef.scene.worldentity)
11525                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11526                                 else
11527                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11528                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11529                                 RSurf_DrawBatch();
11530                         }
11531                 }
11532                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11533                 rsurface.texture = NULL;
11534         }
11535
11536         if (r_shownormals.value != 0 && qglBegin)
11537         {
11538                 if (r_showdisabledepthtest.integer)
11539                 {
11540                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11541                         GL_DepthMask(false);
11542                 }
11543                 else
11544                 {
11545                         GL_BlendFunc(GL_ONE, GL_ZERO);
11546                         GL_DepthMask(true);
11547                 }
11548                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11549                 {
11550                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11551                                 continue;
11552                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11553                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11554                         {
11555                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11556                                 qglBegin(GL_LINES);
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                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11570                                 {
11571                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11572                                         {
11573                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11574                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11575                                                 qglVertex3f(v[0], v[1], v[2]);
11576                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11577                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11578                                                 qglVertex3f(v[0], v[1], v[2]);
11579                                         }
11580                                 }
11581                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11582                                 {
11583                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11584                                         {
11585                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11586                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11587                                                 qglVertex3f(v[0], v[1], v[2]);
11588                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11589                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11590                                                 qglVertex3f(v[0], v[1], v[2]);
11591                                         }
11592                                 }
11593                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11594                                 {
11595                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11596                                         {
11597                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11598                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11599                                                 qglVertex3f(v[0], v[1], v[2]);
11600                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11601                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11602                                                 qglVertex3f(v[0], v[1], v[2]);
11603                                         }
11604                                 }
11605                                 qglEnd();
11606                                 CHECKGLERROR
11607                         }
11608                 }
11609                 rsurface.texture = NULL;
11610         }
11611 #endif
11612 }
11613
11614 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11615 int r_maxsurfacelist = 0;
11616 const msurface_t **r_surfacelist = NULL;
11617 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11618 {
11619         int i, j, endj, flagsmask;
11620         dp_model_t *model = r_refdef.scene.worldmodel;
11621         msurface_t *surfaces;
11622         unsigned char *update;
11623         int numsurfacelist = 0;
11624         if (model == NULL)
11625                 return;
11626
11627         if (r_maxsurfacelist < model->num_surfaces)
11628         {
11629                 r_maxsurfacelist = model->num_surfaces;
11630                 if (r_surfacelist)
11631                         Mem_Free((msurface_t**)r_surfacelist);
11632                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11633         }
11634
11635         RSurf_ActiveWorldEntity();
11636
11637         surfaces = model->data_surfaces;
11638         update = model->brushq1.lightmapupdateflags;
11639
11640         // update light styles on this submodel
11641         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11642         {
11643                 model_brush_lightstyleinfo_t *style;
11644                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11645                 {
11646                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11647                         {
11648                                 int *list = style->surfacelist;
11649                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11650                                 for (j = 0;j < style->numsurfaces;j++)
11651                                         update[list[j]] = true;
11652                         }
11653                 }
11654         }
11655
11656         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11657
11658         if (debug)
11659         {
11660                 R_DrawDebugModel();
11661                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11662                 return;
11663         }
11664
11665         rsurface.lightmaptexture = NULL;
11666         rsurface.deluxemaptexture = NULL;
11667         rsurface.uselightmaptexture = false;
11668         rsurface.texture = NULL;
11669         rsurface.rtlight = NULL;
11670         numsurfacelist = 0;
11671         // add visible surfaces to draw list
11672         for (i = 0;i < model->nummodelsurfaces;i++)
11673         {
11674                 j = model->sortedmodelsurfaces[i];
11675                 if (r_refdef.viewcache.world_surfacevisible[j])
11676                         r_surfacelist[numsurfacelist++] = surfaces + j;
11677         }
11678         // update lightmaps if needed
11679         if (model->brushq1.firstrender)
11680         {
11681                 model->brushq1.firstrender = false;
11682                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11683                         if (update[j])
11684                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11685         }
11686         else if (update)
11687         {
11688                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11689                         if (r_refdef.viewcache.world_surfacevisible[j])
11690                                 if (update[j])
11691                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11692         }
11693         // don't do anything if there were no surfaces
11694         if (!numsurfacelist)
11695         {
11696                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11697                 return;
11698         }
11699         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11700
11701         // add to stats if desired
11702         if (r_speeds.integer && !skysurfaces && !depthonly)
11703         {
11704                 r_refdef.stats.world_surfaces += numsurfacelist;
11705                 for (j = 0;j < numsurfacelist;j++)
11706                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11707         }
11708
11709         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11710 }
11711
11712 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11713 {
11714         int i, j, endj, flagsmask;
11715         dp_model_t *model = ent->model;
11716         msurface_t *surfaces;
11717         unsigned char *update;
11718         int numsurfacelist = 0;
11719         if (model == NULL)
11720                 return;
11721
11722         if (r_maxsurfacelist < model->num_surfaces)
11723         {
11724                 r_maxsurfacelist = model->num_surfaces;
11725                 if (r_surfacelist)
11726                         Mem_Free((msurface_t **)r_surfacelist);
11727                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11728         }
11729
11730         // if the model is static it doesn't matter what value we give for
11731         // wantnormals and wanttangents, so this logic uses only rules applicable
11732         // to a model, knowing that they are meaningless otherwise
11733         if (ent == r_refdef.scene.worldentity)
11734                 RSurf_ActiveWorldEntity();
11735         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11736                 RSurf_ActiveModelEntity(ent, false, false, false);
11737         else if (prepass)
11738                 RSurf_ActiveModelEntity(ent, true, true, true);
11739         else if (depthonly)
11740         {
11741                 switch (vid.renderpath)
11742                 {
11743                 case RENDERPATH_GL20:
11744                 case RENDERPATH_D3D9:
11745                 case RENDERPATH_D3D10:
11746                 case RENDERPATH_D3D11:
11747                 case RENDERPATH_SOFT:
11748                 case RENDERPATH_GLES2:
11749                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11750                         break;
11751                 case RENDERPATH_GL11:
11752                 case RENDERPATH_GL13:
11753                 case RENDERPATH_GLES1:
11754                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11755                         break;
11756                 }
11757         }
11758         else
11759         {
11760                 switch (vid.renderpath)
11761                 {
11762                 case RENDERPATH_GL20:
11763                 case RENDERPATH_D3D9:
11764                 case RENDERPATH_D3D10:
11765                 case RENDERPATH_D3D11:
11766                 case RENDERPATH_SOFT:
11767                 case RENDERPATH_GLES2:
11768                         RSurf_ActiveModelEntity(ent, true, true, false);
11769                         break;
11770                 case RENDERPATH_GL11:
11771                 case RENDERPATH_GL13:
11772                 case RENDERPATH_GLES1:
11773                         RSurf_ActiveModelEntity(ent, true, false, false);
11774                         break;
11775                 }
11776         }
11777
11778         surfaces = model->data_surfaces;
11779         update = model->brushq1.lightmapupdateflags;
11780
11781         // update light styles
11782         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11783         {
11784                 model_brush_lightstyleinfo_t *style;
11785                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11786                 {
11787                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11788                         {
11789                                 int *list = style->surfacelist;
11790                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11791                                 for (j = 0;j < style->numsurfaces;j++)
11792                                         update[list[j]] = true;
11793                         }
11794                 }
11795         }
11796
11797         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11798
11799         if (debug)
11800         {
11801                 R_DrawDebugModel();
11802                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11803                 return;
11804         }
11805
11806         rsurface.lightmaptexture = NULL;
11807         rsurface.deluxemaptexture = NULL;
11808         rsurface.uselightmaptexture = false;
11809         rsurface.texture = NULL;
11810         rsurface.rtlight = NULL;
11811         numsurfacelist = 0;
11812         // add visible surfaces to draw list
11813         for (i = 0;i < model->nummodelsurfaces;i++)
11814                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11815         // don't do anything if there were no surfaces
11816         if (!numsurfacelist)
11817         {
11818                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11819                 return;
11820         }
11821         // update lightmaps if needed
11822         if (update)
11823         {
11824                 int updated = 0;
11825                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11826                 {
11827                         if (update[j])
11828                         {
11829                                 updated++;
11830                                 R_BuildLightMap(ent, surfaces + j);
11831                         }
11832                 }
11833         }
11834         if (update)
11835                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11836                         if (update[j])
11837                                 R_BuildLightMap(ent, surfaces + j);
11838         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11839
11840         // add to stats if desired
11841         if (r_speeds.integer && !skysurfaces && !depthonly)
11842         {
11843                 r_refdef.stats.entities_surfaces += numsurfacelist;
11844                 for (j = 0;j < numsurfacelist;j++)
11845                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11846         }
11847
11848         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11849 }
11850
11851 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11852 {
11853         static texture_t texture;
11854         static msurface_t surface;
11855         const msurface_t *surfacelist = &surface;
11856
11857         // fake enough texture and surface state to render this geometry
11858
11859         texture.update_lastrenderframe = -1; // regenerate this texture
11860         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11861         texture.currentskinframe = skinframe;
11862         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11863         texture.offsetmapping = OFFSETMAPPING_OFF;
11864         texture.offsetscale = 1;
11865         texture.specularscalemod = 1;
11866         texture.specularpowermod = 1;
11867
11868         surface.texture = &texture;
11869         surface.num_triangles = numtriangles;
11870         surface.num_firsttriangle = firsttriangle;
11871         surface.num_vertices = numvertices;
11872         surface.num_firstvertex = firstvertex;
11873
11874         // now render it
11875         rsurface.texture = R_GetCurrentTexture(surface.texture);
11876         rsurface.lightmaptexture = NULL;
11877         rsurface.deluxemaptexture = NULL;
11878         rsurface.uselightmaptexture = false;
11879         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11880 }
11881
11882 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)
11883 {
11884         static msurface_t surface;
11885         const msurface_t *surfacelist = &surface;
11886
11887         // fake enough texture and surface state to render this geometry
11888         surface.texture = texture;
11889         surface.num_triangles = numtriangles;
11890         surface.num_firsttriangle = firsttriangle;
11891         surface.num_vertices = numvertices;
11892         surface.num_firstvertex = firstvertex;
11893
11894         // now render it
11895         rsurface.texture = R_GetCurrentTexture(surface.texture);
11896         rsurface.lightmaptexture = NULL;
11897         rsurface.deluxemaptexture = NULL;
11898         rsurface.uselightmaptexture = false;
11899         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11900 }